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 CyclicPointerTest {
198   int *ptr;
199   CyclicPointerTest() : ptr(reinterpret_cast<int *>(&ptr)) {}
200 };
201 
202 void fCyclicPointerTest() {
203   CyclicPointerTest();
204 }
205 
206 //===----------------------------------------------------------------------===//
207 // Void pointer tests.
208 //===----------------------------------------------------------------------===//
209 
210 // Void pointer tests are mainly no-crash tests.
211 
212 void *malloc(int size);
213 
214 class VoidPointerTest1 {
215   void *vptr;
216 
217 public:
218   VoidPointerTest1(void *vptr, char) : vptr(vptr) {
219     // All good!
220   }
221 };
222 
223 void fVoidPointerTest1() {
224   void *vptr = malloc(sizeof(int));
225   VoidPointerTest1(vptr, char());
226 }
227 
228 class VoidPointerTest2 {
229   void **vpptr;
230 
231 public:
232   VoidPointerTest2(void **vpptr, char) : vpptr(vpptr) {
233     // All good!
234   }
235 };
236 
237 void fVoidPointerTest2() {
238   void *vptr = malloc(sizeof(int));
239   VoidPointerTest2(&vptr, char());
240 }
241 
242 class VoidPointerRRefTest1 {
243   void *&&vptrrref; // expected-note {{here}}
244 
245 public:
246   VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast<void *&&>(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}}
247     // All good!
248   }
249 };
250 
251 void fVoidPointerRRefTest1() {
252   void *vptr = malloc(sizeof(int));
253   VoidPointerRRefTest1(vptr, char());
254 }
255 
256 class VoidPointerRRefTest2 {
257   void **&&vpptrrref; // expected-note {{here}}
258 
259 public:
260   VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast<void **&&>(vptr)) { // expected-warning {{binding reference member 'vpptrrref' to stack allocated parameter 'vptr'}}
261     // All good!
262   }
263 };
264 
265 void fVoidPointerRRefTest2() {
266   void *vptr = malloc(sizeof(int));
267   VoidPointerRRefTest2(&vptr, char());
268 }
269 
270 class VoidPointerLRefTest {
271   void *&vptrrref; // expected-note {{here}}
272 
273 public:
274   VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast<void *&>(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}}
275     // All good!
276   }
277 };
278 
279 void fVoidPointerLRefTest() {
280   void *vptr = malloc(sizeof(int));
281   VoidPointerLRefTest(vptr, char());
282 }
283 
284 struct CyclicVoidPointerTest {
285   void *vptr; // no-crash
286 
287   CyclicVoidPointerTest() : vptr(&vptr) {}
288 };
289 
290 void fCyclicVoidPointerTest() {
291   CyclicVoidPointerTest();
292 }
293 
294 struct IntDynTypedVoidPointerTest1 {
295   void *vptr; // expected-note{{uninitialized pointee 'static_cast<int *>(this->vptr)'}}
296   int dontGetFilteredByNonPedanticMode = 0;
297 
298   IntDynTypedVoidPointerTest1(void *vptr) : vptr(vptr) {} // expected-warning{{1 uninitialized field}}
299 };
300 
301 void fIntDynTypedVoidPointerTest1() {
302   int a;
303   IntDynTypedVoidPointerTest1 tmp(&a);
304 }
305 
306 struct RecordDynTypedVoidPointerTest {
307   struct RecordType {
308     int x; // expected-note{{uninitialized field 'static_cast<struct RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
309     int y; // expected-note{{uninitialized field 'static_cast<struct RecordDynTypedVoidPointerTest::RecordType *>(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 
318 void fRecordDynTypedVoidPointerTest() {
319   RecordDynTypedVoidPointerTest::RecordType a;
320   RecordDynTypedVoidPointerTest tmp(&a);
321 }
322 
323 struct NestedNonVoidDynTypedVoidPointerTest {
324   struct RecordType {
325     int x;      // expected-note{{uninitialized field 'static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
326     int y;      // expected-note{{uninitialized field 'static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
327     void *vptr; // expected-note{{uninitialized pointee 'static_cast<char *>(static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(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 
338 void fNestedNonVoidDynTypedVoidPointerTest() {
339   NestedNonVoidDynTypedVoidPointerTest::RecordType a;
340   char c;
341   NestedNonVoidDynTypedVoidPointerTest tmp(&a, &c);
342 }
343 
344 //===----------------------------------------------------------------------===//
345 // Multipointer tests.
346 //===----------------------------------------------------------------------===//
347 
348 #ifdef PEDANTIC
349 class MultiPointerTest1 {
350 public:
351   struct RecordType {
352     int x;
353     int y;
354   };
355 
356 private:
357   RecordType **mptr; // expected-note{{uninitialized pointee 'this->mptr'}}
358 
359 public:
360   MultiPointerTest1(RecordType **p, int) : mptr(p) { // expected-warning{{1 uninitialized field}}
361   }
362 };
363 
364 void fMultiPointerTest1() {
365   MultiPointerTest1::RecordType *p1;
366   MultiPointerTest1::RecordType **mptr = &p1;
367   MultiPointerTest1(mptr, int()); // '*mptr' uninitialized
368 }
369 #else
370 class MultiPointerTest1 {
371 public:
372   struct RecordType {
373     int x;
374     int y;
375   };
376 
377 private:
378   RecordType **mptr;
379 
380 public:
381   MultiPointerTest1(RecordType **p, int) : mptr(p) {}
382 };
383 
384 void fMultiPointerTest1() {
385   MultiPointerTest1::RecordType *p1;
386   MultiPointerTest1::RecordType **mptr = &p1;
387   MultiPointerTest1(mptr, int()); // '*mptr' uninitialized
388 }
389 #endif // PEDANTIC
390 
391 #ifdef PEDANTIC
392 class MultiPointerTest2 {
393 public:
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 
399 private:
400   RecordType **mptr;
401 
402 public:
403   MultiPointerTest2(RecordType **p, int) : mptr(p) { // expected-warning{{2 uninitialized fields}}
404   }
405 };
406 
407 void fMultiPointerTest2() {
408   MultiPointerTest2::RecordType i;
409   MultiPointerTest2::RecordType *p1 = &i;
410   MultiPointerTest2::RecordType **mptr = &p1;
411   MultiPointerTest2(mptr, int()); // '**mptr' uninitialized
412 }
413 #else
414 class MultiPointerTest2 {
415 public:
416   struct RecordType {
417     int x;
418     int y;
419   };
420 
421 private:
422   RecordType **mptr;
423 
424 public:
425   MultiPointerTest2(RecordType **p, int) : mptr(p) {
426   }
427 };
428 
429 void 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 
437 class MultiPointerTest3 {
438 public:
439   struct RecordType {
440     int x;
441     int y;
442   };
443 
444 private:
445   RecordType **mptr;
446 
447 public:
448   MultiPointerTest3(RecordType **p, int) : mptr(p) {
449     // All good!
450   }
451 };
452 
453 void 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 
464 struct UsefulFunctions {
465   int a, b;
466 
467   void print() {}
468   void dump() {}
469 };
470 
471 #ifdef PEDANTIC
472 struct PointerToMemberFunctionTest1 {
473   void (UsefulFunctions::*f)(void); // expected-note{{uninitialized field 'this->f'}}
474   PointerToMemberFunctionTest1() {}
475 };
476 
477 void fPointerToMemberFunctionTest1() {
478   PointerToMemberFunctionTest1(); // expected-warning{{1 uninitialized field}}
479 }
480 
481 struct PointerToMemberFunctionTest2 {
482   void (UsefulFunctions::*f)(void);
483   PointerToMemberFunctionTest2(void (UsefulFunctions::*f)(void)) : f(f) {
484     // All good!
485   }
486 };
487 
488 void fPointerToMemberFunctionTest2() {
489   void (UsefulFunctions::*f)(void) = &UsefulFunctions::print;
490   PointerToMemberFunctionTest2 a(f);
491 }
492 
493 struct MultiPointerToMemberFunctionTest1 {
494   void (UsefulFunctions::**f)(void); // expected-note{{uninitialized pointer 'this->f'}}
495   MultiPointerToMemberFunctionTest1() {}
496 };
497 
498 void fMultiPointerToMemberFunctionTest1() {
499   MultiPointerToMemberFunctionTest1(); // expected-warning{{1 uninitialized field}}
500 }
501 
502 struct MultiPointerToMemberFunctionTest2 {
503   void (UsefulFunctions::**f)(void);
504   MultiPointerToMemberFunctionTest2(void (UsefulFunctions::**f)(void)) : f(f) {
505     // All good!
506   }
507 };
508 
509 void fMultiPointerToMemberFunctionTest2() {
510   void (UsefulFunctions::*f)(void) = &UsefulFunctions::print;
511   MultiPointerToMemberFunctionTest2 a(&f);
512 }
513 
514 struct PointerToMemberDataTest1 {
515   int UsefulFunctions::*d; // expected-note{{uninitialized field 'this->d'}}
516   PointerToMemberDataTest1() {}
517 };
518 
519 void fPointerToMemberDataTest1() {
520   PointerToMemberDataTest1(); // expected-warning{{1 uninitialized field}}
521 }
522 
523 struct PointerToMemberDataTest2 {
524   int UsefulFunctions::*d;
525   PointerToMemberDataTest2(int UsefulFunctions::*d) : d(d) {
526     // All good!
527   }
528 };
529 
530 void fPointerToMemberDataTest2() {
531   int UsefulFunctions::*d = &UsefulFunctions::a;
532   PointerToMemberDataTest2 a(d);
533 }
534 
535 struct MultiPointerToMemberDataTest1 {
536   int UsefulFunctions::**d; // expected-note{{uninitialized pointer 'this->d'}}
537   MultiPointerToMemberDataTest1() {}
538 };
539 
540 void fMultiPointerToMemberDataTest1() {
541   MultiPointerToMemberDataTest1(); // expected-warning{{1 uninitialized field}}
542 }
543 
544 struct MultiPointerToMemberDataTest2 {
545   int UsefulFunctions::**d;
546   MultiPointerToMemberDataTest2(int UsefulFunctions::**d) : d(d) {
547     // All good!
548   }
549 };
550 
551 void 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 
561 class ListTest1 {
562 public:
563   struct Node {
564     Node *next = nullptr; // no crash
565     int i;
566   };
567 
568 private:
569   Node *head = nullptr;
570 
571 public:
572   ListTest1() {
573     // All good!
574   }
575 };
576 
577 void fListTest1() {
578   ListTest1();
579 }
580 
581 class ListTest2 {
582 public:
583   struct Node {
584     Node *next = nullptr;
585     int i; // expected-note{{uninitialized field 'this->head->i'}}
586   };
587 
588 private:
589   Node *head = nullptr;
590 
591 public:
592   ListTest2(Node *node, int) : head(node) { // expected-warning{{1 uninitialized field}}
593   }
594 };
595 
596 void fListTest2() {
597   ListTest2::Node n;
598   ListTest2(&n, int());
599 }
600 
601 class CyclicList {
602 public:
603   struct Node {
604     Node *next = nullptr;
605     int i; // expected-note{{uninitialized field 'this->head->i'}}
606   };
607 
608 private:
609   Node *head = nullptr;
610 
611 public:
612   CyclicList(Node *node, int) : head(node) { // expected-warning{{1 uninitialized field}}
613   }
614 };
615 
616 void 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 
639 class ReferenceTest1 {
640 public:
641   struct RecordType {
642     int x;
643     int y;
644   };
645 
646 private:
647   RecordType &lref;
648   RecordType &&rref;
649 
650 public:
651   ReferenceTest1(RecordType &lref, RecordType &rref) : lref(lref), rref(static_cast<RecordType &&>(rref)) {
652     // All good!
653   }
654 };
655 
656 void fReferenceTest1() {
657   ReferenceTest1::RecordType d{33, 34};
658   ReferenceTest1(d, d);
659 }
660 
661 #ifdef PEDANTIC
662 class ReferenceTest2 {
663 public:
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 
669 private:
670   RecordType &lref;
671   RecordType &&rref;
672 
673 public:
674   ReferenceTest2(RecordType &lref, RecordType &rref)
675       : lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
676   }
677 };
678 
679 void fReferenceTest2() {
680   ReferenceTest2::RecordType c;
681   ReferenceTest2(c, c);
682 }
683 #else
684 class ReferenceTest2 {
685 public:
686   struct RecordType {
687     int x;
688     int y;
689   };
690 
691 private:
692   RecordType &lref;
693   RecordType &&rref;
694 
695 public:
696   ReferenceTest2(RecordType &lref, RecordType &rref)
697       : lref(lref), rref(static_cast<RecordType &&>(rref)) {
698   }
699 };
700 
701 void fReferenceTest2() {
702   ReferenceTest2::RecordType c;
703   ReferenceTest2(c, c);
704 }
705 #endif // PEDANTIC
706 
707 class ReferenceTest3 {
708 public:
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 
714 private:
715   RecordType &lref;
716   RecordType &&rref;
717 
718 public:
719   ReferenceTest3(RecordType &lref, RecordType &rref)
720       : lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
721   }
722 };
723 
724 void fReferenceTest3() {
725   ReferenceTest3::RecordType c, d{35, 36};
726   ReferenceTest3(c, d);
727 }
728 
729 class ReferenceTest4 {
730 public:
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 
736 private:
737   RecordType &lref;
738   RecordType &&rref;
739 
740 public:
741   ReferenceTest4(RecordType &lref, RecordType &rref)
742       : lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
743   }
744 };
745 
746 void fReferenceTest5() {
747   ReferenceTest4::RecordType c, d{37, 38};
748   ReferenceTest4(d, c);
749 }
750