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 // nonloc::LocAsInteger tests.
26 //===----------------------------------------------------------------------===//
27 
28 using intptr_t = unsigned long long;
29 
30 struct LocAsIntegerTest {
31   intptr_t ptr; // expected-note{{uninitialized pointee 'reinterpret_cast<char *>(this->ptr)'}}
32   int dontGetFilteredByNonPedanticMode = 0;
33 
34   LocAsIntegerTest(void *ptr) : ptr(reinterpret_cast<intptr_t>(ptr)) {} // expected-warning{{1 uninitialized field}}
35 };
36 
37 void fLocAsIntegerTest() {
38   char c;
39   LocAsIntegerTest t(&c);
40 }
41 
42 //===----------------------------------------------------------------------===//
43 // Null pointer tests.
44 //===----------------------------------------------------------------------===//
45 
46 class NullPtrTest {
47   struct RecordType {
48     int x;
49     int y;
50   };
51 
52   float *fptr = nullptr;
53   int *ptr;
54   RecordType *recPtr;
55 
56 public:
57   NullPtrTest() : ptr(nullptr), recPtr(nullptr) {
58     // All good!
59   }
60 };
61 
62 void fNullPtrTest() {
63   NullPtrTest();
64 }
65 
66 //===----------------------------------------------------------------------===//
67 // Alloca tests.
68 //===----------------------------------------------------------------------===//
69 
70 struct UntypedAllocaTest {
71   void *allocaPtr;
72   int dontGetFilteredByNonPedanticMode = 0;
73 
74   UntypedAllocaTest() : allocaPtr(__builtin_alloca(sizeof(int))) {
75     // All good!
76   }
77 };
78 
79 void fUntypedAllocaTest() {
80   UntypedAllocaTest();
81 }
82 
83 struct TypedAllocaTest1 {
84   int *allocaPtr; // expected-note{{uninitialized pointee 'this->allocaPtr'}}
85   int dontGetFilteredByNonPedanticMode = 0;
86 
87   TypedAllocaTest1() // expected-warning{{1 uninitialized field}}
88       : allocaPtr(static_cast<int *>(__builtin_alloca(sizeof(int)))) {}
89 };
90 
91 void fTypedAllocaTest1() {
92   TypedAllocaTest1();
93 }
94 
95 struct TypedAllocaTest2 {
96   int *allocaPtr;
97   int dontGetFilteredByNonPedanticMode = 0;
98 
99   TypedAllocaTest2()
100       : allocaPtr(static_cast<int *>(__builtin_alloca(sizeof(int)))) {
101     *allocaPtr = 55555;
102     // All good!
103   }
104 };
105 
106 void fTypedAllocaTest2() {
107   TypedAllocaTest2();
108 }
109 
110 //===----------------------------------------------------------------------===//
111 // Heap pointer tests.
112 //===----------------------------------------------------------------------===//
113 
114 class HeapPointerTest1 {
115   struct RecordType {
116     // TODO: we'd expect the note: {{uninitialized field 'this->recPtr->y'}}
117     int x; // no-note
118     // TODO: we'd expect the note: {{uninitialized field 'this->recPtr->y'}}
119     int y; // no-note
120   };
121   // TODO: we'd expect the note: {{uninitialized pointee 'this->fptr'}}
122   float *fptr = new float; // no-note
123   // TODO: we'd expect the note: {{uninitialized pointee 'this->ptr'}}
124   int *ptr; // no-note
125   RecordType *recPtr;
126 
127 public:
128   // TODO: we'd expect the warning: {{4 uninitialized fields}}
129   HeapPointerTest1() : ptr(new int), recPtr(new RecordType) { // no-note
130   }
131 };
132 
133 void fHeapPointerTest1() {
134   HeapPointerTest1();
135 }
136 
137 class HeapPointerTest2 {
138   struct RecordType {
139     int x;
140     int y;
141   };
142 
143   float *fptr = new float(); // initializes to 0
144   int *ptr;
145   RecordType *recPtr;
146 
147 public:
148   HeapPointerTest2() : ptr(new int{25}), recPtr(new RecordType{26, 27}) {
149     // All good!
150   }
151 };
152 
153 void fHeapPointerTest2() {
154   HeapPointerTest2();
155 }
156 
157 //===----------------------------------------------------------------------===//
158 // Stack pointer tests.
159 //===----------------------------------------------------------------------===//
160 
161 class StackPointerTest1 {
162 public:
163   struct RecordType {
164     int x;
165     int y;
166   };
167 
168 private:
169   int *ptr;
170   RecordType *recPtr;
171 
172 public:
173   StackPointerTest1(int *_ptr, StackPointerTest1::RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) {
174     // All good!
175   }
176 };
177 
178 void fStackPointerTest1() {
179   int ok_a = 28;
180   StackPointerTest1::RecordType ok_rec{29, 30};
181   StackPointerTest1(&ok_a, &ok_rec); // 'a', 'rec.x', 'rec.y' uninitialized
182 }
183 
184 #ifdef PEDANTIC
185 class StackPointerTest2 {
186 public:
187   struct RecordType {
188     int x; // expected-note{{uninitialized field 'this->recPtr->x'}}
189     int y; // expected-note{{uninitialized field 'this->recPtr->y'}}
190   };
191 
192 private:
193   int *ptr; // expected-note{{uninitialized pointee 'this->ptr'}}
194   RecordType *recPtr;
195 
196 public:
197   StackPointerTest2(int *_ptr, RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) { // expected-warning{{3 uninitialized fields}}
198   }
199 };
200 
201 void fStackPointerTest2() {
202   int a;
203   StackPointerTest2::RecordType rec;
204   StackPointerTest2(&a, &rec); // 'a', 'rec.x', 'rec.y' uninitialized
205 }
206 #else
207 class StackPointerTest2 {
208 public:
209   struct RecordType {
210     int x;
211     int y;
212   };
213 
214 private:
215   int *ptr;
216   RecordType *recPtr;
217 
218 public:
219   StackPointerTest2(int *_ptr, RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) {
220   }
221 };
222 
223 void fStackPointerTest2() {
224   int a;
225   StackPointerTest2::RecordType rec;
226   StackPointerTest2(&a, &rec); // 'a', 'rec.x', 'rec.y' uninitialized
227 }
228 #endif // PEDANTIC
229 
230 class UninitPointerTest {
231   struct RecordType {
232     int x;
233     int y;
234   };
235 
236   int *ptr; // expected-note{{uninitialized pointer 'this->ptr'}}
237   RecordType *recPtr;
238 
239 public:
240   UninitPointerTest() : recPtr(new RecordType{13, 13}) { // expected-warning{{1 uninitialized field}}
241   }
242 };
243 
244 void fUninitPointerTest() {
245   UninitPointerTest();
246 }
247 
248 struct CharPointerTest {
249   const char *str;
250   int dontGetFilteredByNonPedanticMode = 0;
251 
252   CharPointerTest() : str("") {}
253 };
254 
255 void fCharPointerTest() {
256   CharPointerTest();
257 }
258 
259 struct CyclicPointerTest1 {
260   int *ptr; // expected-note{{object references itself 'this->ptr'}}
261   int dontGetFilteredByNonPedanticMode = 0;
262 
263   CyclicPointerTest1() : ptr(reinterpret_cast<int *>(&ptr)) {} // expected-warning{{1 uninitialized field}}
264 };
265 
266 void fCyclicPointerTest1() {
267   CyclicPointerTest1();
268 }
269 
270 struct CyclicPointerTest2 {
271   int **pptr; // expected-note{{object references itself 'this->pptr'}}
272   int dontGetFilteredByNonPedanticMode = 0;
273 
274   CyclicPointerTest2() : pptr(reinterpret_cast<int **>(&pptr)) {} // expected-warning{{1 uninitialized field}}
275 };
276 
277 void fCyclicPointerTest2() {
278   CyclicPointerTest2();
279 }
280 
281 //===----------------------------------------------------------------------===//
282 // Void pointer tests.
283 //===----------------------------------------------------------------------===//
284 
285 // Void pointer tests are mainly no-crash tests.
286 
287 void *malloc(int size);
288 
289 class VoidPointerTest1 {
290   void *vptr;
291 
292 public:
293   VoidPointerTest1(void *vptr, char) : vptr(vptr) {
294     // All good!
295   }
296 };
297 
298 void fVoidPointerTest1() {
299   void *vptr = malloc(sizeof(int));
300   VoidPointerTest1(vptr, char());
301 }
302 
303 class VoidPointerTest2 {
304   void **vpptr;
305 
306 public:
307   VoidPointerTest2(void **vpptr, char) : vpptr(vpptr) {
308     // All good!
309   }
310 };
311 
312 void fVoidPointerTest2() {
313   void *vptr = malloc(sizeof(int));
314   VoidPointerTest2(&vptr, char());
315 }
316 
317 class VoidPointerRRefTest1 {
318   void *&&vptrrref; // expected-note {{here}}
319 
320 public:
321   VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast<void *&&>(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}}
322     // All good!
323   }
324 };
325 
326 void fVoidPointerRRefTest1() {
327   void *vptr = malloc(sizeof(int));
328   VoidPointerRRefTest1(vptr, char());
329 }
330 
331 class VoidPointerRRefTest2 {
332   void **&&vpptrrref; // expected-note {{here}}
333 
334 public:
335   VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast<void **&&>(vptr)) { // expected-warning {{binding reference member 'vpptrrref' to stack allocated parameter 'vptr'}}
336     // All good!
337   }
338 };
339 
340 void fVoidPointerRRefTest2() {
341   void *vptr = malloc(sizeof(int));
342   VoidPointerRRefTest2(&vptr, char());
343 }
344 
345 class VoidPointerLRefTest {
346   void *&vptrrref; // expected-note {{here}}
347 
348 public:
349   VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast<void *&>(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}}
350     // All good!
351   }
352 };
353 
354 void fVoidPointerLRefTest() {
355   void *vptr = malloc(sizeof(int));
356   VoidPointerLRefTest(vptr, char());
357 }
358 
359 struct CyclicVoidPointerTest {
360   void *vptr; // expected-note{{object references itself 'this->vptr'}}
361   int dontGetFilteredByNonPedanticMode = 0;
362 
363   CyclicVoidPointerTest() : vptr(&vptr) {} // expected-warning{{1 uninitialized field}}
364 };
365 
366 void fCyclicVoidPointerTest() {
367   CyclicVoidPointerTest();
368 }
369 
370 struct IntDynTypedVoidPointerTest1 {
371   void *vptr; // expected-note{{uninitialized pointee 'static_cast<int *>(this->vptr)'}}
372   int dontGetFilteredByNonPedanticMode = 0;
373 
374   IntDynTypedVoidPointerTest1(void *vptr) : vptr(vptr) {} // expected-warning{{1 uninitialized field}}
375 };
376 
377 void fIntDynTypedVoidPointerTest1() {
378   int a;
379   IntDynTypedVoidPointerTest1 tmp(&a);
380 }
381 
382 struct RecordDynTypedVoidPointerTest {
383   struct RecordType {
384     int x; // expected-note{{uninitialized field 'static_cast<struct RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
385     int y; // expected-note{{uninitialized field 'static_cast<struct RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
386   };
387 
388   void *vptr;
389   int dontGetFilteredByNonPedanticMode = 0;
390 
391   RecordDynTypedVoidPointerTest(void *vptr) : vptr(vptr) {} // expected-warning{{2 uninitialized fields}}
392 };
393 
394 void fRecordDynTypedVoidPointerTest() {
395   RecordDynTypedVoidPointerTest::RecordType a;
396   RecordDynTypedVoidPointerTest tmp(&a);
397 }
398 
399 struct NestedNonVoidDynTypedVoidPointerTest {
400   struct RecordType {
401     int x;      // expected-note{{uninitialized field 'static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
402     int y;      // expected-note{{uninitialized field 'static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
403     void *vptr; // expected-note{{uninitialized pointee 'static_cast<char *>(static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->vptr)'}}
404   };
405 
406   void *vptr;
407   int dontGetFilteredByNonPedanticMode = 0;
408 
409   NestedNonVoidDynTypedVoidPointerTest(void *vptr, void *c) : vptr(vptr) {
410     static_cast<RecordType *>(vptr)->vptr = c; // expected-warning{{3 uninitialized fields}}
411   }
412 };
413 
414 void fNestedNonVoidDynTypedVoidPointerTest() {
415   NestedNonVoidDynTypedVoidPointerTest::RecordType a;
416   char c;
417   NestedNonVoidDynTypedVoidPointerTest tmp(&a, &c);
418 }
419 
420 //===----------------------------------------------------------------------===//
421 // Multipointer tests.
422 //===----------------------------------------------------------------------===//
423 
424 #ifdef PEDANTIC
425 class MultiPointerTest1 {
426 public:
427   struct RecordType {
428     int x;
429     int y;
430   };
431 
432 private:
433   RecordType **mptr; // expected-note{{uninitialized pointee 'this->mptr'}}
434 
435 public:
436   MultiPointerTest1(RecordType **p, int) : mptr(p) { // expected-warning{{1 uninitialized field}}
437   }
438 };
439 
440 void fMultiPointerTest1() {
441   MultiPointerTest1::RecordType *p1;
442   MultiPointerTest1::RecordType **mptr = &p1;
443   MultiPointerTest1(mptr, int()); // '*mptr' uninitialized
444 }
445 #else
446 class MultiPointerTest1 {
447 public:
448   struct RecordType {
449     int x;
450     int y;
451   };
452 
453 private:
454   RecordType **mptr;
455 
456 public:
457   MultiPointerTest1(RecordType **p, int) : mptr(p) {}
458 };
459 
460 void fMultiPointerTest1() {
461   MultiPointerTest1::RecordType *p1;
462   MultiPointerTest1::RecordType **mptr = &p1;
463   MultiPointerTest1(mptr, int()); // '*mptr' uninitialized
464 }
465 #endif // PEDANTIC
466 
467 #ifdef PEDANTIC
468 class MultiPointerTest2 {
469 public:
470   struct RecordType {
471     int x; // expected-note{{uninitialized field 'this->mptr->x'}}
472     int y; // expected-note{{uninitialized field 'this->mptr->y'}}
473   };
474 
475 private:
476   RecordType **mptr;
477 
478 public:
479   MultiPointerTest2(RecordType **p, int) : mptr(p) { // expected-warning{{2 uninitialized fields}}
480   }
481 };
482 
483 void fMultiPointerTest2() {
484   MultiPointerTest2::RecordType i;
485   MultiPointerTest2::RecordType *p1 = &i;
486   MultiPointerTest2::RecordType **mptr = &p1;
487   MultiPointerTest2(mptr, int()); // '**mptr' uninitialized
488 }
489 #else
490 class MultiPointerTest2 {
491 public:
492   struct RecordType {
493     int x;
494     int y;
495   };
496 
497 private:
498   RecordType **mptr;
499 
500 public:
501   MultiPointerTest2(RecordType **p, int) : mptr(p) {
502   }
503 };
504 
505 void fMultiPointerTest2() {
506   MultiPointerTest2::RecordType i;
507   MultiPointerTest2::RecordType *p1 = &i;
508   MultiPointerTest2::RecordType **mptr = &p1;
509   MultiPointerTest2(mptr, int()); // '**mptr' uninitialized
510 }
511 #endif // PEDANTIC
512 
513 class MultiPointerTest3 {
514 public:
515   struct RecordType {
516     int x;
517     int y;
518   };
519 
520 private:
521   RecordType **mptr;
522 
523 public:
524   MultiPointerTest3(RecordType **p, int) : mptr(p) {
525     // All good!
526   }
527 };
528 
529 void fMultiPointerTest3() {
530   MultiPointerTest3::RecordType i{31, 32};
531   MultiPointerTest3::RecordType *p1 = &i;
532   MultiPointerTest3::RecordType **mptr = &p1;
533   MultiPointerTest3(mptr, int()); // '**mptr' uninitialized
534 }
535 
536 //===----------------------------------------------------------------------===//
537 // Incomplete pointee tests.
538 //===----------------------------------------------------------------------===//
539 
540 class IncompleteType;
541 
542 struct IncompletePointeeTypeTest {
543   IncompleteType *pImpl; //no-crash
544   int dontGetFilteredByNonPedanticMode = 0;
545 
546   IncompletePointeeTypeTest(IncompleteType *A) : pImpl(A) {}
547 };
548 
549 void fIncompletePointeeTypeTest(void *ptr) {
550   IncompletePointeeTypeTest(reinterpret_cast<IncompleteType *>(ptr));
551 }
552 
553 //===----------------------------------------------------------------------===//
554 // Function pointer tests.
555 //===----------------------------------------------------------------------===//
556 
557 struct FunctionPointerWithDifferentDynTypeTest {
558   using Func1 = void *(*)();
559   using Func2 = int *(*)();
560 
561   Func1 f; // no-crash
562   FunctionPointerWithDifferentDynTypeTest(Func2 f) : f((Func1)f) {}
563 };
564 
565 // Note that there isn't a function calling the constructor of
566 // FunctionPointerWithDifferentDynTypeTest, because a crash could only be
567 // reproduced without it.
568 
569 //===----------------------------------------------------------------------===//
570 // Member pointer tests.
571 //===----------------------------------------------------------------------===//
572 
573 struct UsefulFunctions {
574   int a, b;
575 
576   void print() {}
577   void dump() {}
578 };
579 
580 #ifdef PEDANTIC
581 struct PointerToMemberFunctionTest1 {
582   void (UsefulFunctions::*f)(void); // expected-note{{uninitialized field 'this->f'}}
583   PointerToMemberFunctionTest1() {}
584 };
585 
586 void fPointerToMemberFunctionTest1() {
587   PointerToMemberFunctionTest1(); // expected-warning{{1 uninitialized field}}
588 }
589 
590 struct PointerToMemberFunctionTest2 {
591   void (UsefulFunctions::*f)(void);
592   PointerToMemberFunctionTest2(void (UsefulFunctions::*f)(void)) : f(f) {
593     // All good!
594   }
595 };
596 
597 void fPointerToMemberFunctionTest2() {
598   void (UsefulFunctions::*f)(void) = &UsefulFunctions::print;
599   PointerToMemberFunctionTest2 a(f);
600 }
601 
602 struct MultiPointerToMemberFunctionTest1 {
603   void (UsefulFunctions::**f)(void); // expected-note{{uninitialized pointer 'this->f'}}
604   MultiPointerToMemberFunctionTest1() {}
605 };
606 
607 void fMultiPointerToMemberFunctionTest1() {
608   MultiPointerToMemberFunctionTest1(); // expected-warning{{1 uninitialized field}}
609 }
610 
611 struct MultiPointerToMemberFunctionTest2 {
612   void (UsefulFunctions::**f)(void);
613   MultiPointerToMemberFunctionTest2(void (UsefulFunctions::**f)(void)) : f(f) {
614     // All good!
615   }
616 };
617 
618 void fMultiPointerToMemberFunctionTest2() {
619   void (UsefulFunctions::*f)(void) = &UsefulFunctions::print;
620   MultiPointerToMemberFunctionTest2 a(&f);
621 }
622 
623 struct PointerToMemberDataTest1 {
624   int UsefulFunctions::*d; // expected-note{{uninitialized field 'this->d'}}
625   PointerToMemberDataTest1() {}
626 };
627 
628 void fPointerToMemberDataTest1() {
629   PointerToMemberDataTest1(); // expected-warning{{1 uninitialized field}}
630 }
631 
632 struct PointerToMemberDataTest2 {
633   int UsefulFunctions::*d;
634   PointerToMemberDataTest2(int UsefulFunctions::*d) : d(d) {
635     // All good!
636   }
637 };
638 
639 void fPointerToMemberDataTest2() {
640   int UsefulFunctions::*d = &UsefulFunctions::a;
641   PointerToMemberDataTest2 a(d);
642 }
643 
644 struct MultiPointerToMemberDataTest1 {
645   int UsefulFunctions::**d; // expected-note{{uninitialized pointer 'this->d'}}
646   MultiPointerToMemberDataTest1() {}
647 };
648 
649 void fMultiPointerToMemberDataTest1() {
650   MultiPointerToMemberDataTest1(); // expected-warning{{1 uninitialized field}}
651 }
652 
653 struct MultiPointerToMemberDataTest2 {
654   int UsefulFunctions::**d;
655   MultiPointerToMemberDataTest2(int UsefulFunctions::**d) : d(d) {
656     // All good!
657   }
658 };
659 
660 void fMultiPointerToMemberDataTest2() {
661   int UsefulFunctions::*d = &UsefulFunctions::a;
662   MultiPointerToMemberDataTest2 a(&d);
663 }
664 #endif // PEDANTIC
665 
666 //===----------------------------------------------------------------------===//
667 // Tests for list-like records.
668 //===----------------------------------------------------------------------===//
669 
670 class ListTest1 {
671 public:
672   struct Node {
673     Node *next = nullptr; // no crash
674     int i;
675   };
676 
677 private:
678   Node *head = nullptr;
679 
680 public:
681   ListTest1() {
682     // All good!
683   }
684 };
685 
686 void fListTest1() {
687   ListTest1();
688 }
689 
690 class ListTest2 {
691 public:
692   struct Node {
693     Node *next = nullptr;
694     int i; // expected-note{{uninitialized field 'this->head->i'}}
695   };
696 
697 private:
698   Node *head = nullptr;
699 
700 public:
701   ListTest2(Node *node, int) : head(node) { // expected-warning{{1 uninitialized field}}
702   }
703 };
704 
705 void fListTest2() {
706   ListTest2::Node n;
707   ListTest2(&n, int());
708 }
709 
710 class CyclicList {
711 public:
712   struct Node {
713     Node *next = nullptr;
714     int i; // expected-note{{uninitialized field 'this->head->i'}}
715   };
716 
717 private:
718   Node *head = nullptr;
719 
720 public:
721   CyclicList(Node *node, int) : head(node) { // expected-warning{{1 uninitialized field}}
722   }
723 };
724 
725 void fCyclicList() {
726   /*
727                n3
728               /  \
729     this -- n1 -- n2
730   */
731 
732   CyclicList::Node n1;
733   CyclicList::Node n2;
734   n2.next = &n1;
735   n2.i = 50;
736   CyclicList::Node n3;
737   n3.next = &n2;
738   n3.i = 50;
739   n1.next = &n3;
740   // note that n1.i is uninitialized
741   CyclicList(&n1, int());
742 }
743 
744 struct RingListTest {
745   RingListTest *next; // no-crash
746   RingListTest() : next(this) {}
747 };
748 
749 void fRingListTest() {
750   RingListTest();
751 }
752 
753 //===----------------------------------------------------------------------===//
754 // Tests for classes containing references.
755 //===----------------------------------------------------------------------===//
756 
757 class ReferenceTest1 {
758 public:
759   struct RecordType {
760     int x;
761     int y;
762   };
763 
764 private:
765   RecordType &lref;
766   RecordType &&rref;
767 
768 public:
769   ReferenceTest1(RecordType &lref, RecordType &rref) : lref(lref), rref(static_cast<RecordType &&>(rref)) {
770     // All good!
771   }
772 };
773 
774 void fReferenceTest1() {
775   ReferenceTest1::RecordType d{33, 34};
776   ReferenceTest1(d, d);
777 }
778 
779 #ifdef PEDANTIC
780 class ReferenceTest2 {
781 public:
782   struct RecordType {
783     int x; // expected-note{{uninitialized field 'this->lref.x'}}
784     int y; // expected-note{{uninitialized field 'this->lref.y'}}
785   };
786 
787 private:
788   RecordType &lref;
789   RecordType &&rref;
790 
791 public:
792   ReferenceTest2(RecordType &lref, RecordType &rref)
793       : lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
794   }
795 };
796 
797 void fReferenceTest2() {
798   ReferenceTest2::RecordType c;
799   ReferenceTest2(c, c);
800 }
801 #else
802 class ReferenceTest2 {
803 public:
804   struct RecordType {
805     int x;
806     int y;
807   };
808 
809 private:
810   RecordType &lref;
811   RecordType &&rref;
812 
813 public:
814   ReferenceTest2(RecordType &lref, RecordType &rref)
815       : lref(lref), rref(static_cast<RecordType &&>(rref)) {
816   }
817 };
818 
819 void fReferenceTest2() {
820   ReferenceTest2::RecordType c;
821   ReferenceTest2(c, c);
822 }
823 #endif // PEDANTIC
824 
825 class ReferenceTest3 {
826 public:
827   struct RecordType {
828     int x; // expected-note{{uninitialized field 'this->lref.x'}}
829     int y; // expected-note{{uninitialized field 'this->lref.y'}}
830   };
831 
832 private:
833   RecordType &lref;
834   RecordType &&rref;
835 
836 public:
837   ReferenceTest3(RecordType &lref, RecordType &rref)
838       : lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
839   }
840 };
841 
842 void fReferenceTest3() {
843   ReferenceTest3::RecordType c, d{35, 36};
844   ReferenceTest3(c, d);
845 }
846 
847 class ReferenceTest4 {
848 public:
849   struct RecordType {
850     int x; // expected-note{{uninitialized field 'this->rref.x'}}
851     int y; // expected-note{{uninitialized field 'this->rref.y'}}
852   };
853 
854 private:
855   RecordType &lref;
856   RecordType &&rref;
857 
858 public:
859   ReferenceTest4(RecordType &lref, RecordType &rref)
860       : lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
861   }
862 };
863 
864 void fReferenceTest5() {
865   ReferenceTest4::RecordType c, d{37, 38};
866   ReferenceTest4(d, c);
867 }
868 
869 //===----------------------------------------------------------------------===//
870 // Tests for objects containing multiple references to the same object.
871 //===----------------------------------------------------------------------===//
872 
873 struct IntMultipleReferenceToSameObjectTest {
874   int *iptr; // expected-note{{uninitialized pointee 'this->iptr'}}
875   int &iref; // no-note, pointee of this->iref was already reported
876 
877   int dontGetFilteredByNonPedanticMode = 0;
878 
879   IntMultipleReferenceToSameObjectTest(int *i) : iptr(i), iref(*i) {} // expected-warning{{1 uninitialized field}}
880 };
881 
882 void fIntMultipleReferenceToSameObjectTest() {
883   int a;
884   IntMultipleReferenceToSameObjectTest Test(&a);
885 }
886 
887 struct IntReferenceWrapper1 {
888   int &a; // expected-note{{uninitialized pointee 'this->a'}}
889 
890   int dontGetFilteredByNonPedanticMode = 0;
891 
892   IntReferenceWrapper1(int &a) : a(a) {} // expected-warning{{1 uninitialized field}}
893 };
894 
895 struct IntReferenceWrapper2 {
896   int &a; // no-note, pointee of this->a was already reported
897 
898   int dontGetFilteredByNonPedanticMode = 0;
899 
900   IntReferenceWrapper2(int &a) : a(a) {} // no-warning
901 };
902 
903 void fMultipleObjectsReferencingTheSameObjectTest() {
904   int a;
905 
906   IntReferenceWrapper1 T1(a);
907   IntReferenceWrapper2 T2(a);
908 }
909