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