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