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