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