blob: 1507098c5e75718f5262b9338d34a606b8b9a32a [file] [log] [blame]
Kristof Umann30f08652018-06-18 11:50:17 +00001// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -std=c++11 -DPEDANTIC -verify %s
2
3// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -std=c++11 -verify %s
4
5//===----------------------------------------------------------------------===//
6// Concrete location tests.
7//===----------------------------------------------------------------------===//
8
9struct ConcreteIntLocTest {
10 int *ptr;
11
12 ConcreteIntLocTest() : ptr(reinterpret_cast<int *>(0xDEADBEEF)) {}
13};
14
15void fConcreteIntLocTest() {
16 ConcreteIntLocTest();
17}
18
19//===----------------------------------------------------------------------===//
20// Null pointer tests.
21//===----------------------------------------------------------------------===//
22
23class NullPtrTest {
24 struct RecordType {
25 int x;
26 int y;
27 };
28
29 float *fptr = nullptr;
30 int *ptr;
31 RecordType *recPtr;
32
33public:
34 NullPtrTest() : ptr(nullptr), recPtr(nullptr) {
35 // All good!
36 }
37};
38
39void fNullPtrTest() {
40 NullPtrTest();
41}
42
43//===----------------------------------------------------------------------===//
44// Heap pointer tests.
45//===----------------------------------------------------------------------===//
46
47class HeapPointerTest1 {
48 struct RecordType {
49 // TODO: we'd expect the note: {{uninitialized field 'this->recPtr->y'}}
50 int x; // no-note
51 // TODO: we'd expect the note: {{uninitialized field 'this->recPtr->y'}}
52 int y; // no-note
53 };
54 // TODO: we'd expect the note: {{uninitialized pointee 'this->fptr'}}
55 float *fptr = new float; // no-note
56 // TODO: we'd expect the note: {{uninitialized pointee 'this->ptr'}}
57 int *ptr; // no-note
58 RecordType *recPtr;
59
60public:
61 // TODO: we'd expect the warning: {{4 uninitialized fields}}
62 HeapPointerTest1() : ptr(new int), recPtr(new RecordType) { // no-note
63 }
64};
65
66void fHeapPointerTest1() {
67 HeapPointerTest1();
68}
69
70class HeapPointerTest2 {
71 struct RecordType {
72 int x;
73 int y;
74 };
75
76 float *fptr = new float(); // initializes to 0
77 int *ptr;
78 RecordType *recPtr;
79
80public:
81 HeapPointerTest2() : ptr(new int{25}), recPtr(new RecordType{26, 27}) {
82 // All good!
83 }
84};
85
86void fHeapPointerTest2() {
87 HeapPointerTest2();
88}
89
90//===----------------------------------------------------------------------===//
91// Stack pointer tests.
92//===----------------------------------------------------------------------===//
93
94class StackPointerTest1 {
95public:
96 struct RecordType {
97 int x;
98 int y;
99 };
100
101private:
102 int *ptr;
103 RecordType *recPtr;
104
105public:
106 StackPointerTest1(int *_ptr, StackPointerTest1::RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) {
107 // All good!
108 }
109};
110
111void fStackPointerTest1() {
112 int ok_a = 28;
113 StackPointerTest1::RecordType ok_rec{29, 30};
114 StackPointerTest1(&ok_a, &ok_rec); // 'a', 'rec.x', 'rec.y' uninitialized
115}
116
117#ifdef PEDANTIC
118class StackPointerTest2 {
119public:
120 struct RecordType {
121 int x; // expected-note{{uninitialized field 'this->recPtr->x'}}
122 int y; // expected-note{{uninitialized field 'this->recPtr->y'}}
123 };
124
125private:
126 int *ptr; // expected-note{{uninitialized pointee 'this->ptr'}}
127 RecordType *recPtr;
128
129public:
130 StackPointerTest2(int *_ptr, RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) { // expected-warning{{3 uninitialized fields}}
131 }
132};
133
134void fStackPointerTest2() {
135 int a;
136 StackPointerTest2::RecordType rec;
137 StackPointerTest2(&a, &rec); // 'a', 'rec.x', 'rec.y' uninitialized
138}
139#else
140class StackPointerTest2 {
141public:
142 struct RecordType {
143 int x;
144 int y;
145 };
146
147private:
148 int *ptr;
149 RecordType *recPtr;
150
151public:
152 StackPointerTest2(int *_ptr, RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) {
153 }
154};
155
156void fStackPointerTest2() {
157 int a;
158 StackPointerTest2::RecordType rec;
159 StackPointerTest2(&a, &rec); // 'a', 'rec.x', 'rec.y' uninitialized
160}
161#endif // PEDANTIC
162
163class UninitPointerTest {
164 struct RecordType {
165 int x;
166 int y;
167 };
168
169 int *ptr; // expected-note{{uninitialized pointer 'this->ptr'}}
170 RecordType *recPtr;
171
172public:
173 UninitPointerTest() : recPtr(new RecordType{13, 13}) { // expected-warning{{1 uninitialized field}}
174 }
175};
176
177void fUninitPointerTest() {
178 UninitPointerTest();
179}
180
181struct CharPointerTest {
182 const char *str;
183 int dontGetFilteredByNonPedanticMode = 0;
184
185 CharPointerTest() : str("") {}
186};
187
188void fCharPointerTest() {
189 CharPointerTest();
190}
191
192struct CyclicPointerTest {
193 int *ptr;
194 CyclicPointerTest() : ptr(reinterpret_cast<int*>(&ptr)) {}
195};
196
197void fCyclicPointerTest() {
198 CyclicPointerTest();
199}
200
201//===----------------------------------------------------------------------===//
202// Void pointer tests.
203//===----------------------------------------------------------------------===//
204
205// Void pointer tests are mainly no-crash tests.
206
207void *malloc(int size);
208
209class VoidPointerTest1 {
210 void *vptr;
211
212public:
213 VoidPointerTest1(void *vptr, char) : vptr(vptr) {
214 // All good!
215 }
216};
217
218void fVoidPointerTest1() {
219 void *vptr = malloc(sizeof(int));
220 VoidPointerTest1(vptr, char());
221}
222
223class VoidPointerTest2 {
224 void **vpptr;
225
226public:
227 VoidPointerTest2(void **vpptr, char) : vpptr(vpptr) {
228 // All good!
229 }
230};
231
232void fVoidPointerTest2() {
233 void *vptr = malloc(sizeof(int));
234 VoidPointerTest2(&vptr, char());
235}
236
237class VoidPointerRRefTest1 {
Richard Smithca975b22018-07-23 18:50:26 +0000238 void *&&vptrrref; // expected-note {{here}}
Kristof Umann30f08652018-06-18 11:50:17 +0000239
240public:
Richard Smithca975b22018-07-23 18:50:26 +0000241 VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast<void *&&>(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}}
Kristof Umann30f08652018-06-18 11:50:17 +0000242 // All good!
243 }
244};
245
246void fVoidPointerRRefTest1() {
247 void *vptr = malloc(sizeof(int));
248 VoidPointerRRefTest1(vptr, char());
249}
250
251class VoidPointerRRefTest2 {
Richard Smithca975b22018-07-23 18:50:26 +0000252 void **&&vpptrrref; // expected-note {{here}}
Kristof Umann30f08652018-06-18 11:50:17 +0000253
254public:
Richard Smithca975b22018-07-23 18:50:26 +0000255 VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast<void **&&>(vptr)) { // expected-warning {{binding reference member 'vpptrrref' to stack allocated parameter 'vptr'}}
Kristof Umann30f08652018-06-18 11:50:17 +0000256 // All good!
257 }
258};
259
260void fVoidPointerRRefTest2() {
261 void *vptr = malloc(sizeof(int));
262 VoidPointerRRefTest2(&vptr, char());
263}
264
265class VoidPointerLRefTest {
Richard Smithca975b22018-07-23 18:50:26 +0000266 void *&vptrrref; // expected-note {{here}}
Kristof Umann30f08652018-06-18 11:50:17 +0000267
268public:
Richard Smithca975b22018-07-23 18:50:26 +0000269 VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast<void *&>(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}}
Kristof Umann30f08652018-06-18 11:50:17 +0000270 // All good!
271 }
272};
273
274void fVoidPointerLRefTest() {
275 void *vptr = malloc(sizeof(int));
276 VoidPointerLRefTest(vptr, char());
277}
278
279struct CyclicVoidPointerTest {
280 void *vptr; // no-crash
281
282 CyclicVoidPointerTest() : vptr(&vptr) {}
283
284};
285
286void fCyclicVoidPointerTest() {
287 CyclicVoidPointerTest();
288}
289
290//===----------------------------------------------------------------------===//
291// Multipointer tests.
292//===----------------------------------------------------------------------===//
293
294#ifdef PEDANTIC
295class MultiPointerTest1 {
296public:
297 struct RecordType {
298 int x;
299 int y;
300 };
301
302private:
303 RecordType **mptr; // expected-note{{uninitialized pointee 'this->mptr'}}
304
305public:
306 MultiPointerTest1(RecordType **p, int) : mptr(p) { // expected-warning{{1 uninitialized field}}
307 }
308};
309
310void fMultiPointerTest1() {
311 MultiPointerTest1::RecordType *p1;
312 MultiPointerTest1::RecordType **mptr = &p1;
313 MultiPointerTest1(mptr, int()); // '*mptr' uninitialized
314}
315#else
316class MultiPointerTest1 {
317public:
318 struct RecordType {
319 int x;
320 int y;
321 };
322
323private:
324 RecordType **mptr;
325
326public:
327 MultiPointerTest1(RecordType **p, int) : mptr(p) {}
328};
329
330void fMultiPointerTest1() {
331 MultiPointerTest1::RecordType *p1;
332 MultiPointerTest1::RecordType **mptr = &p1;
333 MultiPointerTest1(mptr, int()); // '*mptr' uninitialized
334}
335#endif // PEDANTIC
336
337#ifdef PEDANTIC
338class MultiPointerTest2 {
339public:
340 struct RecordType {
341 int x; // expected-note{{uninitialized field 'this->mptr->x'}}
342 int y; // expected-note{{uninitialized field 'this->mptr->y'}}
343 };
344
345private:
346 RecordType **mptr;
347
348public:
349 MultiPointerTest2(RecordType **p, int) : mptr(p) { // expected-warning{{2 uninitialized fields}}
350 }
351};
352
353void fMultiPointerTest2() {
354 MultiPointerTest2::RecordType i;
355 MultiPointerTest2::RecordType *p1 = &i;
356 MultiPointerTest2::RecordType **mptr = &p1;
357 MultiPointerTest2(mptr, int()); // '**mptr' uninitialized
358}
359#else
360class MultiPointerTest2 {
361public:
362 struct RecordType {
363 int x;
364 int y;
365 };
366
367private:
368 RecordType **mptr;
369
370public:
371 MultiPointerTest2(RecordType **p, int) : mptr(p) {
372 }
373};
374
375void fMultiPointerTest2() {
376 MultiPointerTest2::RecordType i;
377 MultiPointerTest2::RecordType *p1 = &i;
378 MultiPointerTest2::RecordType **mptr = &p1;
379 MultiPointerTest2(mptr, int()); // '**mptr' uninitialized
380}
381#endif // PEDANTIC
382
383class MultiPointerTest3 {
384public:
385 struct RecordType {
386 int x;
387 int y;
388 };
389
390private:
391 RecordType **mptr;
392
393public:
394 MultiPointerTest3(RecordType **p, int) : mptr(p) {
395 // All good!
396 }
397};
398
399void fMultiPointerTest3() {
400 MultiPointerTest3::RecordType i{31, 32};
401 MultiPointerTest3::RecordType *p1 = &i;
402 MultiPointerTest3::RecordType **mptr = &p1;
403 MultiPointerTest3(mptr, int()); // '**mptr' uninitialized
404}
405
406//===----------------------------------------------------------------------===//
407// Member pointer tests.
408//===----------------------------------------------------------------------===//
409
410struct UsefulFunctions {
411 int a, b;
412
413 void print() {}
414 void dump() {}
415};
416
417#ifdef PEDANTIC
418struct PointerToMemberFunctionTest1 {
Kristof Umann7212cc02018-07-13 12:21:38 +0000419 void (UsefulFunctions::*f)(void); // expected-note{{uninitialized field 'this->f'}}
Kristof Umann30f08652018-06-18 11:50:17 +0000420 PointerToMemberFunctionTest1() {}
421};
422
423void fPointerToMemberFunctionTest1() {
Kristof Umann7212cc02018-07-13 12:21:38 +0000424 PointerToMemberFunctionTest1(); // expected-warning{{1 uninitialized field}}
Kristof Umann30f08652018-06-18 11:50:17 +0000425}
426
427struct PointerToMemberFunctionTest2 {
428 void (UsefulFunctions::*f)(void);
429 PointerToMemberFunctionTest2(void (UsefulFunctions::*f)(void)) : f(f) {
430 // All good!
431 }
432};
433
434void fPointerToMemberFunctionTest2() {
435 void (UsefulFunctions::*f)(void) = &UsefulFunctions::print;
436 PointerToMemberFunctionTest2 a(f);
437}
438
439struct MultiPointerToMemberFunctionTest1 {
440 void (UsefulFunctions::**f)(void); // expected-note{{uninitialized pointer 'this->f'}}
441 MultiPointerToMemberFunctionTest1() {}
442};
443
444void fMultiPointerToMemberFunctionTest1() {
445 MultiPointerToMemberFunctionTest1(); // expected-warning{{1 uninitialized field}}
446}
447
448struct MultiPointerToMemberFunctionTest2 {
449 void (UsefulFunctions::**f)(void);
450 MultiPointerToMemberFunctionTest2(void (UsefulFunctions::**f)(void)) : f(f) {
451 // All good!
452 }
453};
454
455void fMultiPointerToMemberFunctionTest2() {
456 void (UsefulFunctions::*f)(void) = &UsefulFunctions::print;
457 MultiPointerToMemberFunctionTest2 a(&f);
458}
459
460struct PointerToMemberDataTest1 {
Kristof Umann7212cc02018-07-13 12:21:38 +0000461 int UsefulFunctions::*d; // expected-note{{uninitialized field 'this->d'}}
Kristof Umann30f08652018-06-18 11:50:17 +0000462 PointerToMemberDataTest1() {}
463};
464
465void fPointerToMemberDataTest1() {
Kristof Umann7212cc02018-07-13 12:21:38 +0000466 PointerToMemberDataTest1(); // expected-warning{{1 uninitialized field}}
Kristof Umann30f08652018-06-18 11:50:17 +0000467}
468
469struct PointerToMemberDataTest2 {
470 int UsefulFunctions::*d;
471 PointerToMemberDataTest2(int UsefulFunctions::*d) : d(d) {
472 // All good!
473 }
474};
475
476void fPointerToMemberDataTest2() {
477 int UsefulFunctions::*d = &UsefulFunctions::a;
478 PointerToMemberDataTest2 a(d);
479}
480
481struct MultiPointerToMemberDataTest1 {
482 int UsefulFunctions::**d; // expected-note{{uninitialized pointer 'this->d'}}
483 MultiPointerToMemberDataTest1() {}
484};
485
486void fMultiPointerToMemberDataTest1() {
487 MultiPointerToMemberDataTest1(); // expected-warning{{1 uninitialized field}}
488}
489
490struct MultiPointerToMemberDataTest2 {
491 int UsefulFunctions::**d;
492 MultiPointerToMemberDataTest2(int UsefulFunctions::**d) : d(d) {
493 // All good!
494 }
495};
496
497void fMultiPointerToMemberDataTest2() {
498 int UsefulFunctions::*d = &UsefulFunctions::a;
499 MultiPointerToMemberDataTest2 a(&d);
500}
501#endif // PEDANTIC
502
503//===----------------------------------------------------------------------===//
504// Tests for list-like records.
505//===----------------------------------------------------------------------===//
506
507class ListTest1 {
508public:
509 struct Node {
510 Node *next = nullptr; // no crash
511 int i;
512 };
513
514private:
515 Node *head = nullptr;
516
517public:
518 ListTest1() {
519 // All good!
520 }
521};
522
523void fListTest1() {
524 ListTest1();
525}
526
527class ListTest2 {
528public:
529 struct Node {
530 Node *next = nullptr;
531 int i; // expected-note{{uninitialized field 'this->head->i'}}
532 };
533
534private:
535 Node *head = nullptr;
536
537public:
538 ListTest2(Node *node, int) : head(node) { // expected-warning{{1 uninitialized field}}
539 }
540};
541
542void fListTest2() {
543 ListTest2::Node n;
544 ListTest2(&n, int());
545}
546
547class CyclicList {
548public:
549 struct Node {
550 Node *next = nullptr;
551 int i; // expected-note{{uninitialized field 'this->head->i'}}
552 };
553
554private:
555 Node *head = nullptr;
556
557public:
558 CyclicList(Node *node, int) : head(node) { // expected-warning{{1 uninitialized field}}
559 }
560};
561
562void fCyclicList() {
563 /*
564 n3
565 / \
566 this -- n1 -- n2
567 */
568
569 CyclicList::Node n1;
570 CyclicList::Node n2;
571 n2.next = &n1;
572 n2.i = 50;
573 CyclicList::Node n3;
574 n3.next = &n2;
575 n3.i = 50;
576 n1.next = &n3;
577 // note that n1.i is uninitialized
578 CyclicList(&n1, int());
579}
580
581//===----------------------------------------------------------------------===//
582// Tests for classes containing references.
583//===----------------------------------------------------------------------===//
584
585class ReferenceTest1 {
586public:
587 struct RecordType {
588 int x;
589 int y;
590 };
591
592private:
593 RecordType &lref;
594 RecordType &&rref;
595
596public:
597 ReferenceTest1(RecordType &lref, RecordType &rref) : lref(lref), rref(static_cast<RecordType &&>(rref)) {
598 // All good!
599 }
600};
601
602void fReferenceTest1() {
603 ReferenceTest1::RecordType d{33, 34};
604 ReferenceTest1(d, d);
605}
606
607#ifdef PEDANTIC
608class ReferenceTest2 {
609public:
610 struct RecordType {
611 int x; // expected-note{{uninitialized field 'this->lref.x'}}
612 int y; // expected-note{{uninitialized field 'this->lref.y'}}
613 };
614
615private:
616 RecordType &lref;
617 RecordType &&rref;
618
619public:
620 ReferenceTest2(RecordType &lref, RecordType &rref)
621 : lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
622 }
623};
624
625void fReferenceTest2() {
626 ReferenceTest2::RecordType c;
627 ReferenceTest2(c, c);
628}
629#else
630class ReferenceTest2 {
631public:
632 struct RecordType {
633 int x;
634 int y;
635 };
636
637private:
638 RecordType &lref;
639 RecordType &&rref;
640
641public:
642 ReferenceTest2(RecordType &lref, RecordType &rref)
643 : lref(lref), rref(static_cast<RecordType &&>(rref)) {
644 }
645};
646
647void fReferenceTest2() {
648 ReferenceTest2::RecordType c;
649 ReferenceTest2(c, c);
650}
651#endif // PEDANTIC
652
653class ReferenceTest3 {
654public:
655 struct RecordType {
656 int x; // expected-note{{uninitialized field 'this->lref.x'}}
657 int y; // expected-note{{uninitialized field 'this->lref.y'}}
658 };
659
660private:
661 RecordType &lref;
662 RecordType &&rref;
663
664public:
665 ReferenceTest3(RecordType &lref, RecordType &rref)
666 : lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
667 }
668};
669
670void fReferenceTest3() {
671 ReferenceTest3::RecordType c, d{35, 36};
672 ReferenceTest3(c, d);
673}
674
675class ReferenceTest4 {
676public:
677 struct RecordType {
678 int x; // expected-note{{uninitialized field 'this->rref.x'}}
679 int y; // expected-note{{uninitialized field 'this->rref.y'}}
680 };
681
682private:
683 RecordType &lref;
684 RecordType &&rref;
685
686public:
687 ReferenceTest4(RecordType &lref, RecordType &rref)
688 : lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
689 }
690};
691
692void fReferenceTest5() {
693 ReferenceTest4::RecordType c, d{37, 38};
694 ReferenceTest4(d, c);
695}