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