1// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify %s 2 3#include "Inputs/system-header-simulator-cxx.h" 4 5void clang_analyzer_eval(bool); 6void clang_analyzer_checkInlined(bool); 7 8// A simplified version of std::move. 9template <typename T> 10T &&move(T &obj) { 11 return static_cast<T &&>(obj); 12} 13 14 15struct Wrapper { 16 __strong id obj; 17}; 18 19void test() { 20 Wrapper w; 21 // force a diagnostic 22 *(char *)0 = 1; // expected-warning{{Dereference of null pointer}} 23} 24 25 26struct IntWrapper { 27 int x; 28}; 29 30void testCopyConstructor() { 31 IntWrapper a; 32 a.x = 42; 33 34 IntWrapper b(a); 35 clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}} 36} 37 38struct NonPODIntWrapper { 39 int x; 40 41 virtual int get(); 42}; 43 44void testNonPODCopyConstructor() { 45 NonPODIntWrapper a; 46 a.x = 42; 47 48 NonPODIntWrapper b(a); 49 clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}} 50} 51 52 53namespace ConstructorVirtualCalls { 54 class A { 55 public: 56 int *out1, *out2, *out3; 57 58 virtual int get() { return 1; } 59 60 A(int *out1) { 61 *out1 = get(); 62 } 63 }; 64 65 class B : public A { 66 public: 67 virtual int get() { return 2; } 68 69 B(int *out1, int *out2) : A(out1) { 70 *out2 = get(); 71 } 72 }; 73 74 class C : public B { 75 public: 76 virtual int get() { return 3; } 77 78 C(int *out1, int *out2, int *out3) : B(out1, out2) { 79 *out3 = get(); 80 } 81 }; 82 83 void test() { 84 int a, b, c; 85 86 C obj(&a, &b, &c); 87 clang_analyzer_eval(a == 1); // expected-warning{{TRUE}} 88 clang_analyzer_eval(b == 2); // expected-warning{{TRUE}} 89 clang_analyzer_eval(c == 3); // expected-warning{{TRUE}} 90 91 clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}} 92 93 // Sanity check for devirtualization. 94 A *base = &obj; 95 clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}} 96 } 97} 98 99namespace TemporaryConstructor { 100 class BoolWrapper { 101 public: 102 BoolWrapper() { 103 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}} 104 value = true; 105 } 106 bool value; 107 }; 108 109 void test() { 110 // PR13717 - Don't crash when a CXXTemporaryObjectExpr is inlined. 111 if (BoolWrapper().value) 112 return; 113 } 114} 115 116 117namespace ConstructorUsedAsRValue { 118 using TemporaryConstructor::BoolWrapper; 119 120 bool extractValue(BoolWrapper b) { 121 return b.value; 122 } 123 124 void test() { 125 bool result = extractValue(BoolWrapper()); 126 clang_analyzer_eval(result); // expected-warning{{TRUE}} 127 } 128} 129 130namespace PODUninitialized { 131 class POD { 132 public: 133 int x, y; 134 }; 135 136 class PODWrapper { 137 public: 138 POD p; 139 }; 140 141 class NonPOD { 142 public: 143 int x, y; 144 145 NonPOD() {} 146 NonPOD(const NonPOD &Other) 147 : x(Other.x), y(Other.y) // expected-warning {{undefined}} 148 { 149 } 150 NonPOD(NonPOD &&Other) 151 : x(Other.x), y(Other.y) // expected-warning {{undefined}} 152 { 153 } 154 155 NonPOD &operator=(const NonPOD &Other) 156 { 157 x = Other.x; 158 y = Other.y; // expected-warning {{undefined}} 159 return *this; 160 } 161 NonPOD &operator=(NonPOD &&Other) 162 { 163 x = Other.x; 164 y = Other.y; // expected-warning {{undefined}} 165 return *this; 166 } 167 }; 168 169 class NonPODWrapper { 170 public: 171 class Inner { 172 public: 173 int x, y; 174 175 Inner() {} 176 Inner(const Inner &Other) 177 : x(Other.x), y(Other.y) // expected-warning {{undefined}} 178 { 179 } 180 Inner(Inner &&Other) 181 : x(Other.x), y(Other.y) // expected-warning {{undefined}} 182 { 183 } 184 185 Inner &operator=(const Inner &Other) 186 { 187 x = Other.x; // expected-warning {{undefined}} 188 y = Other.y; 189 return *this; 190 } 191 Inner &operator=(Inner &&Other) 192 { 193 x = Other.x; // expected-warning {{undefined}} 194 y = Other.y; 195 return *this; 196 } 197 }; 198 199 Inner p; 200 }; 201 202 void testPOD() { 203 POD p; 204 p.x = 1; 205 POD p2 = p; // no-warning 206 clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}} 207 POD p3 = move(p); // no-warning 208 clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}} 209 210 // Use rvalues as well. 211 clang_analyzer_eval(POD(p3).x == 1); // expected-warning{{TRUE}} 212 213 PODWrapper w; 214 w.p.y = 1; 215 PODWrapper w2 = w; // no-warning 216 clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}} 217 PODWrapper w3 = move(w); // no-warning 218 clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}} 219 220 // Use rvalues as well. 221 clang_analyzer_eval(PODWrapper(w3).p.y == 1); // expected-warning{{TRUE}} 222 } 223 224 void testNonPOD() { 225 NonPOD p; 226 p.x = 1; 227 NonPOD p2 = p; 228 } 229 230 void testNonPODMove() { 231 NonPOD p; 232 p.x = 1; 233 NonPOD p2 = move(p); 234 } 235 236 void testNonPODWrapper() { 237 NonPODWrapper w; 238 w.p.y = 1; 239 NonPODWrapper w2 = w; 240 } 241 242 void testNonPODWrapperMove() { 243 NonPODWrapper w; 244 w.p.y = 1; 245 NonPODWrapper w2 = move(w); 246 } 247 248 // Not strictly about constructors, but trivial assignment operators should 249 // essentially work the same way. 250 namespace AssignmentOperator { 251 void testPOD() { 252 POD p; 253 p.x = 1; 254 POD p2; 255 p2 = p; // no-warning 256 clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}} 257 POD p3; 258 p3 = move(p); // no-warning 259 clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}} 260 261 PODWrapper w; 262 w.p.y = 1; 263 PODWrapper w2; 264 w2 = w; // no-warning 265 clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}} 266 PODWrapper w3; 267 w3 = move(w); // no-warning 268 clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}} 269 } 270 271 void testReturnValue() { 272 POD p; 273 p.x = 1; 274 POD p2; 275 clang_analyzer_eval(&(p2 = p) == &p2); // expected-warning{{TRUE}} 276 277 PODWrapper w; 278 w.p.y = 1; 279 PODWrapper w2; 280 clang_analyzer_eval(&(w2 = w) == &w2); // expected-warning{{TRUE}} 281 } 282 283 void testNonPOD() { 284 NonPOD p; 285 p.x = 1; 286 NonPOD p2; 287 p2 = p; 288 } 289 290 void testNonPODMove() { 291 NonPOD p; 292 p.x = 1; 293 NonPOD p2; 294 p2 = move(p); 295 } 296 297 void testNonPODWrapper() { 298 NonPODWrapper w; 299 w.p.y = 1; 300 NonPODWrapper w2; 301 w2 = w; 302 } 303 304 void testNonPODWrapperMove() { 305 NonPODWrapper w; 306 w.p.y = 1; 307 NonPODWrapper w2; 308 w2 = move(w); 309 } 310 } 311} 312 313namespace ArrayMembers { 314 struct Primitive { 315 int values[3]; 316 }; 317 318 void testPrimitive() { 319 Primitive a = { { 1, 2, 3 } }; 320 321 clang_analyzer_eval(a.values[0] == 1); // expected-warning{{TRUE}} 322 clang_analyzer_eval(a.values[1] == 2); // expected-warning{{TRUE}} 323 clang_analyzer_eval(a.values[2] == 3); // expected-warning{{TRUE}} 324 325 Primitive b = a; 326 327 clang_analyzer_eval(b.values[0] == 1); // expected-warning{{TRUE}} 328 clang_analyzer_eval(b.values[1] == 2); // expected-warning{{TRUE}} 329 clang_analyzer_eval(b.values[2] == 3); // expected-warning{{TRUE}} 330 331 Primitive c; 332 c = b; 333 334 clang_analyzer_eval(c.values[0] == 1); // expected-warning{{TRUE}} 335 clang_analyzer_eval(c.values[1] == 2); // expected-warning{{TRUE}} 336 clang_analyzer_eval(c.values[2] == 3); // expected-warning{{TRUE}} 337 } 338 339 struct NestedPrimitive { 340 int values[2][3]; 341 }; 342 343 void testNestedPrimitive() { 344 NestedPrimitive a = { { { 0, 0, 0 }, { 1, 2, 3 } } }; 345 346 clang_analyzer_eval(a.values[1][0] == 1); // expected-warning{{TRUE}} 347 clang_analyzer_eval(a.values[1][1] == 2); // expected-warning{{TRUE}} 348 clang_analyzer_eval(a.values[1][2] == 3); // expected-warning{{TRUE}} 349 350 NestedPrimitive b = a; 351 352 clang_analyzer_eval(b.values[1][0] == 1); // expected-warning{{TRUE}} 353 clang_analyzer_eval(b.values[1][1] == 2); // expected-warning{{TRUE}} 354 clang_analyzer_eval(b.values[1][2] == 3); // expected-warning{{TRUE}} 355 356 NestedPrimitive c; 357 c = b; 358 359 clang_analyzer_eval(c.values[1][0] == 1); // expected-warning{{TRUE}} 360 clang_analyzer_eval(c.values[1][1] == 2); // expected-warning{{TRUE}} 361 clang_analyzer_eval(c.values[1][2] == 3); // expected-warning{{TRUE}} 362 } 363 364 struct POD { 365 IntWrapper values[3]; 366 }; 367 368 void testPOD() { 369 POD a = { { { 1 }, { 2 }, { 3 } } }; 370 371 clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}} 372 clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}} 373 clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}} 374 375 POD b = a; 376 377 clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{TRUE}} 378 clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{TRUE}} 379 clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{TRUE}} 380 381 POD c; 382 c = b; 383 384 clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{TRUE}} 385 clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{TRUE}} 386 clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{TRUE}} 387 } 388 389 struct NestedPOD { 390 IntWrapper values[2][3]; 391 }; 392 393 void testNestedPOD() { 394 NestedPOD a = { { { { 0 }, { 0 }, { 0 } }, { { 1 }, { 2 }, { 3 } } } }; 395 396 clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}} 397 clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}} 398 clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}} 399 400 NestedPOD b = a; 401 402 clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{TRUE}} 403 clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{TRUE}} 404 clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{TRUE}} 405 406 NestedPOD c; 407 c = b; 408 409 clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{TRUE}} 410 clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{TRUE}} 411 clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{TRUE}} 412 } 413 414 struct NonPOD { 415 NonPODIntWrapper values[3]; 416 }; 417 418 void testNonPOD() { 419 NonPOD a; 420 a.values[0].x = 1; 421 a.values[1].x = 2; 422 a.values[2].x = 3; 423 424 clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}} 425 clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}} 426 clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}} 427 428 NonPOD b = a; 429 430 clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{UNKNOWN}} 431 clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{UNKNOWN}} 432 clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{UNKNOWN}} 433 434 NonPOD c; 435 c = b; 436 437 clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{UNKNOWN}} 438 clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{UNKNOWN}} 439 clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}} 440 } 441 442 struct NestedNonPOD { 443 NonPODIntWrapper values[2][3]; 444 }; 445 446 void testNestedNonPOD() { 447 NestedNonPOD a; 448 a.values[0][0].x = 0; 449 a.values[0][1].x = 0; 450 a.values[0][2].x = 0; 451 a.values[1][0].x = 1; 452 a.values[1][1].x = 2; 453 a.values[1][2].x = 3; 454 455 clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}} 456 clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}} 457 clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}} 458 459 NestedNonPOD b = a; 460 461 clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{UNKNOWN}} 462 clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{UNKNOWN}} 463 clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{UNKNOWN}} 464 465 NestedNonPOD c; 466 c = b; 467 468 clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{UNKNOWN}} 469 clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{UNKNOWN}} 470 clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{UNKNOWN}} 471 } 472 473 struct NonPODDefaulted { 474 NonPODIntWrapper values[3]; 475 476 NonPODDefaulted() = default; 477 NonPODDefaulted(const NonPODDefaulted &) = default; 478 NonPODDefaulted &operator=(const NonPODDefaulted &) = default; 479 }; 480 481 void testNonPODDefaulted() { 482 NonPODDefaulted a; 483 a.values[0].x = 1; 484 a.values[1].x = 2; 485 a.values[2].x = 3; 486 487 clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}} 488 clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}} 489 clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}} 490 491 NonPODDefaulted b = a; 492 493 clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{UNKNOWN}} 494 clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{UNKNOWN}} 495 clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{UNKNOWN}} 496 497 NonPODDefaulted c; 498 c = b; 499 500 clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{UNKNOWN}} 501 clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{UNKNOWN}} 502 clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}} 503 } 504}; 505 506namespace VirtualInheritance { 507 int counter; 508 509 struct base { 510 base() { 511 ++counter; 512 } 513 }; 514 515 struct virtual_subclass : public virtual base { 516 virtual_subclass() {} 517 }; 518 519 struct double_subclass : public virtual_subclass { 520 double_subclass() {} 521 }; 522 523 void test() { 524 counter = 0; 525 double_subclass obj; 526 clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}} 527 } 528 529 struct double_virtual_subclass : public virtual virtual_subclass { 530 double_virtual_subclass() {} 531 }; 532 533 void testVirtual() { 534 counter = 0; 535 double_virtual_subclass obj; 536 clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}} 537 } 538} 539 540namespace ZeroInitialization { 541 struct raw_pair { 542 int p1; 543 int p2; 544 }; 545 546 void testVarDecl() { 547 raw_pair p{}; 548 clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}} 549 clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}} 550 } 551 552 void testTemporary() { 553 clang_analyzer_eval(raw_pair().p1 == 0); // expected-warning{{TRUE}} 554 clang_analyzer_eval(raw_pair().p2 == 0); // expected-warning{{TRUE}} 555 } 556 557 void testArray() { 558 raw_pair p[2] = {}; 559 clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{TRUE}} 560 clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{TRUE}} 561 clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{TRUE}} 562 clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{TRUE}} 563 } 564 565 void testNew() { 566 // FIXME: Pending proper implementation of constructors for 'new'. 567 raw_pair *pp = new raw_pair(); 568 clang_analyzer_eval(pp->p1 == 0); // expected-warning{{UNKNOWN}} 569 clang_analyzer_eval(pp->p2 == 0); // expected-warning{{UNKNOWN}} 570 } 571 572 void testArrayNew() { 573 // FIXME: Pending proper implementation of constructors for 'new[]'. 574 raw_pair *p = new raw_pair[2](); 575 clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{UNKNOWN}} 576 clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{UNKNOWN}} 577 clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{UNKNOWN}} 578 clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{UNKNOWN}} 579 } 580 581 struct initializing_pair { 582 public: 583 int x; 584 raw_pair y; 585 initializing_pair() : x(), y() {} 586 }; 587 588 void testFieldInitializers() { 589 initializing_pair p; 590 clang_analyzer_eval(p.x == 0); // expected-warning{{TRUE}} 591 clang_analyzer_eval(p.y.p1 == 0); // expected-warning{{TRUE}} 592 clang_analyzer_eval(p.y.p2 == 0); // expected-warning{{TRUE}} 593 } 594 595 struct subclass : public raw_pair { 596 subclass() = default; 597 }; 598 599 void testSubclass() { 600 subclass p; 601 clang_analyzer_eval(p.p1 == 0); // expected-warning{{garbage}} 602 } 603 604 struct initializing_subclass : public raw_pair { 605 initializing_subclass() : raw_pair() {} 606 }; 607 608 void testInitializingSubclass() { 609 initializing_subclass p; 610 clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}} 611 clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}} 612 } 613 614 struct pair_wrapper { 615 pair_wrapper() : p() {} 616 raw_pair p; 617 }; 618 619 struct virtual_subclass : public virtual pair_wrapper { 620 virtual_subclass() {} 621 }; 622 623 struct double_virtual_subclass : public virtual_subclass { 624 double_virtual_subclass() { 625 // This previously caused a crash because the pair_wrapper subobject was 626 // initialized twice. 627 } 628 }; 629 630 class Empty { 631 public: 632 Empty(); 633 }; 634 635 class PairContainer : public Empty { 636 raw_pair p; 637 public: 638 PairContainer() : Empty(), p() { 639 // This previously caused a crash because the empty base class looked 640 // like an initialization of 'p'. 641 } 642 PairContainer(int) : Empty(), p() { 643 // Test inlining something else here. 644 } 645 }; 646 647 class PairContainerContainer { 648 int padding; 649 PairContainer pc; 650 public: 651 PairContainerContainer() : pc(1) {} 652 }; 653} 654 655namespace InitializerList { 656 struct List { 657 bool usedInitializerList; 658 659 List() : usedInitializerList(false) {} 660 List(std::initializer_list<int>) : usedInitializerList(true) {} 661 }; 662 663 void testStatic() { 664 List defaultCtor; 665 clang_analyzer_eval(!defaultCtor.usedInitializerList); // expected-warning{{TRUE}} 666 667 List list{1, 2}; 668 clang_analyzer_eval(list.usedInitializerList); // expected-warning{{TRUE}} 669 } 670 671 void testDynamic() { 672 List *list = new List{1, 2}; 673 // FIXME: When we handle constructors with 'new', this will be TRUE. 674 clang_analyzer_eval(list->usedInitializerList); // expected-warning{{UNKNOWN}} 675 } 676} 677