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