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