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