1 //===- unittests/Analysis/FlowSensitive/TransferTest.cpp ------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "TestingSupport.h" 10 #include "clang/AST/ASTContext.h" 11 #include "clang/AST/Decl.h" 12 #include "clang/ASTMatchers/ASTMatchers.h" 13 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" 14 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" 15 #include "clang/Analysis/FlowSensitive/RecordOps.h" 16 #include "clang/Analysis/FlowSensitive/StorageLocation.h" 17 #include "clang/Analysis/FlowSensitive/Value.h" 18 #include "clang/Basic/LangStandard.h" 19 #include "llvm/ADT/ArrayRef.h" 20 #include "llvm/ADT/SmallVector.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/Support/Casting.h" 23 #include "llvm/Testing/Support/Error.h" 24 #include "gmock/gmock.h" 25 #include "gtest/gtest.h" 26 #include <optional> 27 #include <string> 28 #include <utility> 29 30 namespace { 31 32 using namespace clang; 33 using namespace dataflow; 34 using namespace test; 35 using ::testing::Eq; 36 using ::testing::IsNull; 37 using ::testing::Ne; 38 using ::testing::NotNull; 39 using ::testing::UnorderedElementsAre; 40 41 void runDataflow( 42 llvm::StringRef Code, 43 std::function< 44 void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &, 45 ASTContext &)> 46 VerifyResults, 47 DataflowAnalysisOptions Options, 48 LangStandard::Kind Std = LangStandard::lang_cxx17, 49 llvm::StringRef TargetFun = "target") { 50 ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code, VerifyResults, Options, 51 Std, TargetFun), 52 llvm::Succeeded()); 53 } 54 55 void runDataflow( 56 llvm::StringRef Code, 57 std::function< 58 void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &, 59 ASTContext &)> 60 VerifyResults, 61 LangStandard::Kind Std = LangStandard::lang_cxx17, 62 bool ApplyBuiltinTransfer = true, llvm::StringRef TargetFun = "target") { 63 runDataflow(Code, std::move(VerifyResults), 64 {ApplyBuiltinTransfer ? BuiltinOptions{} 65 : std::optional<BuiltinOptions>()}, 66 Std, TargetFun); 67 } 68 69 const Formula &getFormula(const ValueDecl &D, const Environment &Env) { 70 return cast<BoolValue>(Env.getValue(D))->formula(); 71 } 72 73 TEST(TransferTest, CNotSupported) { 74 std::string Code = R"( 75 void target() {} 76 )"; 77 ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis( 78 Code, [](const auto &, auto &) {}, {BuiltinOptions{}}, 79 LangStandard::lang_c89), 80 llvm::FailedWithMessage("Can only analyze C++")); 81 } 82 83 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) { 84 std::string Code = R"( 85 void target() { 86 int Foo; 87 // [[p]] 88 } 89 )"; 90 runDataflow( 91 Code, 92 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 93 ASTContext &ASTCtx) { 94 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 95 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 96 97 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 98 ASSERT_THAT(FooDecl, NotNull()); 99 100 EXPECT_EQ(Env.getStorageLocation(*FooDecl), nullptr); 101 }, 102 LangStandard::lang_cxx17, 103 /*ApplyBuiltinTransfer=*/false); 104 } 105 106 TEST(TransferTest, BoolVarDecl) { 107 std::string Code = R"( 108 void target() { 109 bool Foo; 110 // [[p]] 111 } 112 )"; 113 runDataflow( 114 Code, 115 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 116 ASTContext &ASTCtx) { 117 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 118 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 119 120 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 121 ASSERT_THAT(FooDecl, NotNull()); 122 123 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 124 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 125 126 const Value *FooVal = Env.getValue(*FooLoc); 127 EXPECT_TRUE(isa_and_nonnull<BoolValue>(FooVal)); 128 }); 129 } 130 131 TEST(TransferTest, IntVarDecl) { 132 std::string Code = R"( 133 void target() { 134 int Foo; 135 // [[p]] 136 } 137 )"; 138 runDataflow( 139 Code, 140 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 141 ASTContext &ASTCtx) { 142 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 143 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 144 145 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 146 ASSERT_THAT(FooDecl, NotNull()); 147 148 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 149 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 150 151 const Value *FooVal = Env.getValue(*FooLoc); 152 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 153 }); 154 } 155 156 TEST(TransferTest, StructIncomplete) { 157 std::string Code = R"( 158 struct A; 159 160 void target() { 161 A* Foo; 162 // [[p]] 163 } 164 )"; 165 runDataflow( 166 Code, 167 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 168 ASTContext &ASTCtx) { 169 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 170 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 171 172 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 173 ASSERT_THAT(FooDecl, NotNull()); 174 auto *FooValue = dyn_cast_or_null<PointerValue>(Env.getValue(*FooDecl)); 175 ASSERT_THAT(FooValue, NotNull()); 176 177 EXPECT_TRUE(isa<RecordStorageLocation>(FooValue->getPointeeLoc())); 178 auto *FooPointeeValue = Env.getValue(FooValue->getPointeeLoc()); 179 ASSERT_THAT(FooPointeeValue, NotNull()); 180 EXPECT_TRUE(isa<RecordValue>(FooPointeeValue)); 181 }); 182 } 183 184 // As a memory optimization, we prevent modeling fields nested below a certain 185 // level (currently, depth 3). This test verifies this lack of modeling. We also 186 // include a regression test for the case that the unmodeled field is a 187 // reference to a struct; previously, we crashed when accessing such a field. 188 TEST(TransferTest, StructFieldUnmodeled) { 189 std::string Code = R"( 190 struct S { int X; }; 191 S GlobalS; 192 struct A { S &Unmodeled = GlobalS; }; 193 struct B { A F3; }; 194 struct C { B F2; }; 195 struct D { C F1; }; 196 197 void target() { 198 D Bar; 199 A &Foo = Bar.F1.F2.F3; 200 int Zab = Foo.Unmodeled.X; 201 // [[p]] 202 } 203 )"; 204 runDataflow( 205 Code, 206 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 207 ASTContext &ASTCtx) { 208 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 209 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 210 211 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 212 ASSERT_THAT(FooDecl, NotNull()); 213 QualType FooReferentType = FooDecl->getType()->getPointeeType(); 214 ASSERT_TRUE(FooReferentType->isStructureType()); 215 auto FooFields = FooReferentType->getAsRecordDecl()->fields(); 216 217 FieldDecl *UnmodeledDecl = nullptr; 218 for (FieldDecl *Field : FooFields) { 219 if (Field->getNameAsString() == "Unmodeled") { 220 UnmodeledDecl = Field; 221 } else { 222 FAIL() << "Unexpected field: " << Field->getNameAsString(); 223 } 224 } 225 ASSERT_THAT(UnmodeledDecl, NotNull()); 226 227 const auto *FooLoc = 228 cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 229 const auto *UnmodeledLoc = FooLoc->getChild(*UnmodeledDecl); 230 ASSERT_TRUE(isa<RecordStorageLocation>(UnmodeledLoc)); 231 EXPECT_THAT(Env.getValue(*UnmodeledLoc), IsNull()); 232 233 const ValueDecl *ZabDecl = findValueDecl(ASTCtx, "Zab"); 234 ASSERT_THAT(ZabDecl, NotNull()); 235 EXPECT_THAT(Env.getValue(*ZabDecl), NotNull()); 236 }); 237 } 238 239 TEST(TransferTest, StructVarDecl) { 240 std::string Code = R"( 241 struct A { 242 int Bar; 243 }; 244 245 void target() { 246 A Foo; 247 (void)Foo.Bar; 248 // [[p]] 249 } 250 )"; 251 runDataflow( 252 Code, 253 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 254 ASTContext &ASTCtx) { 255 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 256 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 257 258 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 259 ASSERT_THAT(FooDecl, NotNull()); 260 261 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 262 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 263 264 FieldDecl *BarDecl = nullptr; 265 for (FieldDecl *Field : FooFields) { 266 if (Field->getNameAsString() == "Bar") { 267 BarDecl = Field; 268 } else { 269 FAIL() << "Unexpected field: " << Field->getNameAsString(); 270 } 271 } 272 ASSERT_THAT(BarDecl, NotNull()); 273 274 const auto *FooLoc = 275 cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 276 EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env))); 277 }); 278 } 279 280 TEST(TransferTest, StructVarDeclWithInit) { 281 std::string Code = R"( 282 struct A { 283 int Bar; 284 }; 285 286 A Gen(); 287 288 void target() { 289 A Foo = Gen(); 290 (void)Foo.Bar; 291 // [[p]] 292 } 293 )"; 294 runDataflow( 295 Code, 296 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 297 ASTContext &ASTCtx) { 298 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 299 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 300 301 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 302 ASSERT_THAT(FooDecl, NotNull()); 303 304 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 305 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 306 307 FieldDecl *BarDecl = nullptr; 308 for (FieldDecl *Field : FooFields) { 309 if (Field->getNameAsString() == "Bar") { 310 BarDecl = Field; 311 } else { 312 FAIL() << "Unexpected field: " << Field->getNameAsString(); 313 } 314 } 315 ASSERT_THAT(BarDecl, NotNull()); 316 317 const auto *FooLoc = 318 cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 319 EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env))); 320 }); 321 } 322 323 TEST(TransferTest, StructArrayVarDecl) { 324 std::string Code = R"( 325 struct A {}; 326 327 void target() { 328 A Array[2]; 329 // [[p]] 330 } 331 )"; 332 runDataflow( 333 Code, 334 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 335 ASTContext &ASTCtx) { 336 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 337 338 const ValueDecl *ArrayDecl = findValueDecl(ASTCtx, "Array"); 339 340 // We currently don't create values for arrays. 341 ASSERT_THAT(Env.getValue(*ArrayDecl), IsNull()); 342 }); 343 } 344 345 TEST(TransferTest, ClassVarDecl) { 346 std::string Code = R"( 347 class A { 348 public: 349 int Bar; 350 }; 351 352 void target() { 353 A Foo; 354 (void)Foo.Bar; 355 // [[p]] 356 } 357 )"; 358 runDataflow( 359 Code, 360 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 361 ASTContext &ASTCtx) { 362 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 363 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 364 365 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 366 ASSERT_THAT(FooDecl, NotNull()); 367 368 ASSERT_TRUE(FooDecl->getType()->isClassType()); 369 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 370 371 FieldDecl *BarDecl = nullptr; 372 for (FieldDecl *Field : FooFields) { 373 if (Field->getNameAsString() == "Bar") { 374 BarDecl = Field; 375 } else { 376 FAIL() << "Unexpected field: " << Field->getNameAsString(); 377 } 378 } 379 ASSERT_THAT(BarDecl, NotNull()); 380 381 const auto *FooLoc = 382 cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 383 EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env))); 384 }); 385 } 386 387 TEST(TransferTest, ReferenceVarDecl) { 388 std::string Code = R"( 389 struct A {}; 390 391 A &getA(); 392 393 void target() { 394 A &Foo = getA(); 395 // [[p]] 396 } 397 )"; 398 runDataflow( 399 Code, 400 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 401 ASTContext &ASTCtx) { 402 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 403 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 404 405 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 406 ASSERT_THAT(FooDecl, NotNull()); 407 408 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 409 ASSERT_TRUE(isa_and_nonnull<RecordStorageLocation>(FooLoc)); 410 411 const Value *FooReferentVal = Env.getValue(*FooLoc); 412 EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooReferentVal)); 413 }); 414 } 415 416 TEST(TransferTest, SelfReferentialReferenceVarDecl) { 417 std::string Code = R"( 418 struct A; 419 420 struct B {}; 421 422 struct C { 423 A &FooRef; 424 A *FooPtr; 425 B &BazRef; 426 B *BazPtr; 427 }; 428 429 struct A { 430 C &Bar; 431 }; 432 433 A &getA(); 434 435 void target() { 436 A &Foo = getA(); 437 (void)Foo.Bar.FooRef; 438 (void)Foo.Bar.FooPtr; 439 (void)Foo.Bar.BazRef; 440 (void)Foo.Bar.BazPtr; 441 // [[p]] 442 } 443 )"; 444 runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> 445 &Results, 446 ASTContext &ASTCtx) { 447 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 448 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 449 450 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 451 ASSERT_THAT(FooDecl, NotNull()); 452 453 ASSERT_TRUE(FooDecl->getType()->isReferenceType()); 454 ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType()); 455 const auto FooFields = 456 FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields(); 457 458 FieldDecl *BarDecl = nullptr; 459 for (FieldDecl *Field : FooFields) { 460 if (Field->getNameAsString() == "Bar") { 461 BarDecl = Field; 462 } else { 463 FAIL() << "Unexpected field: " << Field->getNameAsString(); 464 } 465 } 466 ASSERT_THAT(BarDecl, NotNull()); 467 468 ASSERT_TRUE(BarDecl->getType()->isReferenceType()); 469 ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType()); 470 const auto BarFields = 471 BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields(); 472 473 FieldDecl *FooRefDecl = nullptr; 474 FieldDecl *FooPtrDecl = nullptr; 475 FieldDecl *BazRefDecl = nullptr; 476 FieldDecl *BazPtrDecl = nullptr; 477 for (FieldDecl *Field : BarFields) { 478 if (Field->getNameAsString() == "FooRef") { 479 FooRefDecl = Field; 480 } else if (Field->getNameAsString() == "FooPtr") { 481 FooPtrDecl = Field; 482 } else if (Field->getNameAsString() == "BazRef") { 483 BazRefDecl = Field; 484 } else if (Field->getNameAsString() == "BazPtr") { 485 BazPtrDecl = Field; 486 } else { 487 FAIL() << "Unexpected field: " << Field->getNameAsString(); 488 } 489 } 490 ASSERT_THAT(FooRefDecl, NotNull()); 491 ASSERT_THAT(FooPtrDecl, NotNull()); 492 ASSERT_THAT(BazRefDecl, NotNull()); 493 ASSERT_THAT(BazPtrDecl, NotNull()); 494 495 const auto &FooLoc = 496 *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 497 498 const auto &BarLoc = 499 *cast<RecordStorageLocation>(FooLoc.getChild(*BarDecl)); 500 501 const auto &FooReferentLoc = 502 *cast<RecordStorageLocation>(BarLoc.getChild(*FooRefDecl)); 503 EXPECT_THAT(Env.getValue(FooReferentLoc), NotNull()); 504 EXPECT_THAT(getFieldValue(&FooReferentLoc, *BarDecl, Env), IsNull()); 505 506 const auto &FooPtrVal = 507 *cast<PointerValue>(getFieldValue(&BarLoc, *FooPtrDecl, Env)); 508 const auto &FooPtrPointeeLoc = 509 cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc()); 510 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), NotNull()); 511 EXPECT_THAT(getFieldValue(&FooPtrPointeeLoc, *BarDecl, Env), IsNull()); 512 513 EXPECT_THAT(getFieldValue(&BarLoc, *BazRefDecl, Env), NotNull()); 514 515 const auto &BazPtrVal = 516 *cast<PointerValue>(getFieldValue(&BarLoc, *BazPtrDecl, Env)); 517 const StorageLocation &BazPtrPointeeLoc = BazPtrVal.getPointeeLoc(); 518 EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); 519 }); 520 } 521 522 TEST(TransferTest, PointerVarDecl) { 523 std::string Code = R"( 524 struct A {}; 525 526 A *getA(); 527 528 void target() { 529 A *Foo = getA(); 530 // [[p]] 531 } 532 )"; 533 runDataflow( 534 Code, 535 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 536 ASTContext &ASTCtx) { 537 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 538 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 539 540 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 541 ASSERT_THAT(FooDecl, NotNull()); 542 543 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 544 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 545 546 const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 547 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 548 EXPECT_TRUE(isa<RecordStorageLocation>(&FooPointeeLoc)); 549 550 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 551 EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooPointeeVal)); 552 }); 553 } 554 555 TEST(TransferTest, SelfReferentialPointerVarDecl) { 556 std::string Code = R"( 557 struct A; 558 559 struct B {}; 560 561 struct C { 562 A &FooRef; 563 A *FooPtr; 564 B &BazRef; 565 B *BazPtr; 566 }; 567 568 struct A { 569 C *Bar; 570 }; 571 572 A *getA(); 573 574 void target() { 575 A *Foo = getA(); 576 (void)Foo->Bar->FooRef; 577 (void)Foo->Bar->FooPtr; 578 (void)Foo->Bar->BazRef; 579 (void)Foo->Bar->BazPtr; 580 // [[p]] 581 } 582 )"; 583 runDataflow( 584 Code, 585 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 586 ASTContext &ASTCtx) { 587 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 588 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 589 590 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 591 ASSERT_THAT(FooDecl, NotNull()); 592 593 ASSERT_TRUE(FooDecl->getType()->isPointerType()); 594 ASSERT_TRUE(FooDecl->getType() 595 ->getAs<PointerType>() 596 ->getPointeeType() 597 ->isStructureType()); 598 const auto FooFields = FooDecl->getType() 599 ->getAs<PointerType>() 600 ->getPointeeType() 601 ->getAsRecordDecl() 602 ->fields(); 603 604 FieldDecl *BarDecl = nullptr; 605 for (FieldDecl *Field : FooFields) { 606 if (Field->getNameAsString() == "Bar") { 607 BarDecl = Field; 608 } else { 609 FAIL() << "Unexpected field: " << Field->getNameAsString(); 610 } 611 } 612 ASSERT_THAT(BarDecl, NotNull()); 613 614 ASSERT_TRUE(BarDecl->getType()->isPointerType()); 615 ASSERT_TRUE(BarDecl->getType() 616 ->getAs<PointerType>() 617 ->getPointeeType() 618 ->isStructureType()); 619 const auto BarFields = BarDecl->getType() 620 ->getAs<PointerType>() 621 ->getPointeeType() 622 ->getAsRecordDecl() 623 ->fields(); 624 625 FieldDecl *FooRefDecl = nullptr; 626 FieldDecl *FooPtrDecl = nullptr; 627 FieldDecl *BazRefDecl = nullptr; 628 FieldDecl *BazPtrDecl = nullptr; 629 for (FieldDecl *Field : BarFields) { 630 if (Field->getNameAsString() == "FooRef") { 631 FooRefDecl = Field; 632 } else if (Field->getNameAsString() == "FooPtr") { 633 FooPtrDecl = Field; 634 } else if (Field->getNameAsString() == "BazRef") { 635 BazRefDecl = Field; 636 } else if (Field->getNameAsString() == "BazPtr") { 637 BazPtrDecl = Field; 638 } else { 639 FAIL() << "Unexpected field: " << Field->getNameAsString(); 640 } 641 } 642 ASSERT_THAT(FooRefDecl, NotNull()); 643 ASSERT_THAT(FooPtrDecl, NotNull()); 644 ASSERT_THAT(BazRefDecl, NotNull()); 645 ASSERT_THAT(BazPtrDecl, NotNull()); 646 647 const auto &FooLoc = 648 *cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl)); 649 const auto &FooVal = *cast<PointerValue>(Env.getValue(FooLoc)); 650 const auto &FooPointeeVal = 651 *cast<RecordValue>(Env.getValue(FooVal.getPointeeLoc())); 652 653 const auto &BarVal = 654 *cast<PointerValue>(getFieldValue(&FooPointeeVal, *BarDecl, Env)); 655 const auto &BarPointeeVal = 656 *cast<RecordValue>(Env.getValue(BarVal.getPointeeLoc())); 657 658 EXPECT_THAT(getFieldValue(&BarPointeeVal, *FooRefDecl, Env), NotNull()); 659 660 const auto &FooPtrVal = *cast<PointerValue>( 661 getFieldValue(&BarPointeeVal, *FooPtrDecl, Env)); 662 const auto &FooPtrPointeeLoc = 663 cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc()); 664 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull()); 665 666 EXPECT_THAT(getFieldValue(&BarPointeeVal, *BazRefDecl, Env), NotNull()); 667 668 const auto &BazPtrVal = *cast<PointerValue>( 669 getFieldValue(&BarPointeeVal, *BazPtrDecl, Env)); 670 const StorageLocation &BazPtrPointeeLoc = BazPtrVal.getPointeeLoc(); 671 EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); 672 }); 673 } 674 675 TEST(TransferTest, DirectlySelfReferentialReference) { 676 std::string Code = R"( 677 struct target { 678 target() { 679 (void)0; 680 // [[p]] 681 } 682 target &self = *this; 683 }; 684 )"; 685 runDataflow( 686 Code, 687 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 688 ASTContext &ASTCtx) { 689 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 690 const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "self"); 691 692 auto *ThisLoc = Env.getThisPointeeStorageLocation(); 693 ASSERT_EQ(ThisLoc->getChild(*SelfDecl), ThisLoc); 694 }); 695 } 696 697 TEST(TransferTest, MultipleVarsDecl) { 698 std::string Code = R"( 699 void target() { 700 int Foo, Bar; 701 (void)0; 702 // [[p]] 703 } 704 )"; 705 runDataflow( 706 Code, 707 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 708 ASTContext &ASTCtx) { 709 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 710 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 711 712 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 713 ASSERT_THAT(FooDecl, NotNull()); 714 715 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 716 ASSERT_THAT(BarDecl, NotNull()); 717 718 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 719 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 720 721 const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl); 722 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 723 724 const Value *FooVal = Env.getValue(*FooLoc); 725 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 726 727 const Value *BarVal = Env.getValue(*BarLoc); 728 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 729 }); 730 } 731 732 TEST(TransferTest, JoinVarDecl) { 733 std::string Code = R"( 734 void target(bool B) { 735 int Foo; 736 // [[p1]] 737 if (B) { 738 int Bar; 739 // [[p2]] 740 } else { 741 int Baz; 742 // [[p3]] 743 } 744 (void)0; 745 // [[p4]] 746 } 747 )"; 748 runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> 749 &Results, 750 ASTContext &ASTCtx) { 751 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2", "p3", "p4")); 752 753 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 754 ASSERT_THAT(FooDecl, NotNull()); 755 756 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 757 ASSERT_THAT(BarDecl, NotNull()); 758 759 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 760 ASSERT_THAT(BazDecl, NotNull()); 761 762 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 763 764 const StorageLocation *FooLoc = Env1.getStorageLocation(*FooDecl); 765 EXPECT_THAT(FooLoc, NotNull()); 766 EXPECT_THAT(Env1.getStorageLocation(*BarDecl), IsNull()); 767 EXPECT_THAT(Env1.getStorageLocation(*BazDecl), IsNull()); 768 769 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 770 EXPECT_EQ(Env2.getStorageLocation(*FooDecl), FooLoc); 771 EXPECT_THAT(Env2.getStorageLocation(*BarDecl), NotNull()); 772 EXPECT_THAT(Env2.getStorageLocation(*BazDecl), IsNull()); 773 774 const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3"); 775 EXPECT_EQ(Env3.getStorageLocation(*FooDecl), FooLoc); 776 EXPECT_THAT(Env3.getStorageLocation(*BarDecl), IsNull()); 777 EXPECT_THAT(Env3.getStorageLocation(*BazDecl), NotNull()); 778 779 const Environment &Env4 = getEnvironmentAtAnnotation(Results, "p4"); 780 EXPECT_EQ(Env4.getStorageLocation(*FooDecl), FooLoc); 781 EXPECT_THAT(Env4.getStorageLocation(*BarDecl), IsNull()); 782 EXPECT_THAT(Env4.getStorageLocation(*BazDecl), IsNull()); 783 }); 784 } 785 786 TEST(TransferTest, BinaryOperatorAssign) { 787 std::string Code = R"( 788 void target() { 789 int Foo; 790 int Bar; 791 (Bar) = (Foo); 792 // [[p]] 793 } 794 )"; 795 runDataflow( 796 Code, 797 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 798 ASTContext &ASTCtx) { 799 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 800 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 801 802 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 803 ASSERT_THAT(FooDecl, NotNull()); 804 805 const Value *FooVal = Env.getValue(*FooDecl); 806 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 807 808 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 809 ASSERT_THAT(BarDecl, NotNull()); 810 811 EXPECT_EQ(Env.getValue(*BarDecl), FooVal); 812 }); 813 } 814 815 TEST(TransferTest, BinaryOperatorAssignIntegerLiteral) { 816 std::string Code = R"( 817 void target() { 818 int Foo = 1; 819 // [[before]] 820 Foo = 2; 821 // [[after]] 822 } 823 )"; 824 runDataflow( 825 Code, 826 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 827 ASTContext &ASTCtx) { 828 const Environment &Before = 829 getEnvironmentAtAnnotation(Results, "before"); 830 const Environment &After = getEnvironmentAtAnnotation(Results, "after"); 831 832 const auto &ValBefore = 833 getValueForDecl<IntegerValue>(ASTCtx, Before, "Foo"); 834 const auto &ValAfter = 835 getValueForDecl<IntegerValue>(ASTCtx, After, "Foo"); 836 EXPECT_NE(&ValBefore, &ValAfter); 837 }); 838 } 839 840 TEST(TransferTest, VarDeclInitAssign) { 841 std::string Code = R"( 842 void target() { 843 int Foo; 844 int Bar = Foo; 845 // [[p]] 846 } 847 )"; 848 runDataflow( 849 Code, 850 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 851 ASTContext &ASTCtx) { 852 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 853 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 854 855 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 856 ASSERT_THAT(FooDecl, NotNull()); 857 858 const Value *FooVal = Env.getValue(*FooDecl); 859 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 860 861 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 862 ASSERT_THAT(BarDecl, NotNull()); 863 864 EXPECT_EQ(Env.getValue(*BarDecl), FooVal); 865 }); 866 } 867 868 TEST(TransferTest, VarDeclInitAssignChained) { 869 std::string Code = R"( 870 void target() { 871 int Foo; 872 int Bar; 873 int Baz = (Bar = Foo); 874 // [[p]] 875 } 876 )"; 877 runDataflow( 878 Code, 879 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 880 ASTContext &ASTCtx) { 881 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 882 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 883 884 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 885 ASSERT_THAT(FooDecl, NotNull()); 886 887 const Value *FooVal = Env.getValue(*FooDecl); 888 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 889 890 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 891 ASSERT_THAT(BarDecl, NotNull()); 892 893 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 894 ASSERT_THAT(BazDecl, NotNull()); 895 896 EXPECT_EQ(Env.getValue(*BarDecl), FooVal); 897 EXPECT_EQ(Env.getValue(*BazDecl), FooVal); 898 }); 899 } 900 901 TEST(TransferTest, VarDeclInitAssignPtrDeref) { 902 std::string Code = R"( 903 void target() { 904 int Foo; 905 int *Bar; 906 *(Bar) = Foo; 907 int Baz = *(Bar); 908 // [[p]] 909 } 910 )"; 911 runDataflow( 912 Code, 913 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 914 ASTContext &ASTCtx) { 915 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 916 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 917 918 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 919 ASSERT_THAT(FooDecl, NotNull()); 920 921 const Value *FooVal = Env.getValue(*FooDecl); 922 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 923 924 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 925 ASSERT_THAT(BarDecl, NotNull()); 926 927 const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl)); 928 EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal); 929 930 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 931 ASSERT_THAT(BazDecl, NotNull()); 932 933 EXPECT_EQ(Env.getValue(*BazDecl), FooVal); 934 }); 935 } 936 937 TEST(TransferTest, AssignToAndFromReference) { 938 std::string Code = R"( 939 void target() { 940 int Foo; 941 int Bar; 942 int &Baz = Foo; 943 // [[p1]] 944 Baz = Bar; 945 int Qux = Baz; 946 int &Quux = Baz; 947 // [[p2]] 948 } 949 )"; 950 runDataflow( 951 Code, 952 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 953 ASTContext &ASTCtx) { 954 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 955 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 956 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 957 958 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 959 ASSERT_THAT(FooDecl, NotNull()); 960 961 const Value *FooVal = Env1.getValue(*FooDecl); 962 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 963 964 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 965 ASSERT_THAT(BarDecl, NotNull()); 966 967 const Value *BarVal = Env1.getValue(*BarDecl); 968 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 969 970 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 971 ASSERT_THAT(BazDecl, NotNull()); 972 973 EXPECT_EQ(Env1.getValue(*BazDecl), FooVal); 974 975 EXPECT_EQ(Env2.getValue(*BazDecl), BarVal); 976 EXPECT_EQ(Env2.getValue(*FooDecl), BarVal); 977 978 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 979 ASSERT_THAT(QuxDecl, NotNull()); 980 EXPECT_EQ(Env2.getValue(*QuxDecl), BarVal); 981 982 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 983 ASSERT_THAT(QuuxDecl, NotNull()); 984 EXPECT_EQ(Env2.getValue(*QuuxDecl), BarVal); 985 }); 986 } 987 988 TEST(TransferTest, MultipleParamDecls) { 989 std::string Code = R"( 990 void target(int Foo, int Bar) { 991 (void)0; 992 // [[p]] 993 } 994 )"; 995 runDataflow( 996 Code, 997 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 998 ASTContext &ASTCtx) { 999 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1000 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1001 1002 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1003 ASSERT_THAT(FooDecl, NotNull()); 1004 1005 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 1006 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 1007 1008 const Value *FooVal = Env.getValue(*FooLoc); 1009 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 1010 1011 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1012 ASSERT_THAT(BarDecl, NotNull()); 1013 1014 const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl); 1015 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1016 1017 const Value *BarVal = Env.getValue(*BarLoc); 1018 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1019 }); 1020 } 1021 1022 TEST(TransferTest, StructParamDecl) { 1023 std::string Code = R"( 1024 struct A { 1025 int Bar; 1026 }; 1027 1028 void target(A Foo) { 1029 (void)Foo.Bar; 1030 // [[p]] 1031 } 1032 )"; 1033 runDataflow( 1034 Code, 1035 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1036 ASTContext &ASTCtx) { 1037 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1038 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1039 1040 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1041 ASSERT_THAT(FooDecl, NotNull()); 1042 1043 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1044 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1045 1046 FieldDecl *BarDecl = nullptr; 1047 for (FieldDecl *Field : FooFields) { 1048 if (Field->getNameAsString() == "Bar") { 1049 BarDecl = Field; 1050 } else { 1051 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1052 } 1053 } 1054 ASSERT_THAT(BarDecl, NotNull()); 1055 1056 const auto *FooLoc = 1057 cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 1058 EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env))); 1059 }); 1060 } 1061 1062 TEST(TransferTest, ReferenceParamDecl) { 1063 std::string Code = R"( 1064 struct A {}; 1065 1066 void target(A &Foo) { 1067 (void)0; 1068 // [[p]] 1069 } 1070 )"; 1071 runDataflow( 1072 Code, 1073 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1074 ASTContext &ASTCtx) { 1075 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1076 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1077 1078 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1079 ASSERT_THAT(FooDecl, NotNull()); 1080 1081 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 1082 ASSERT_TRUE(isa_and_nonnull<RecordStorageLocation>(FooLoc)); 1083 1084 const Value *FooReferentVal = Env.getValue(*FooLoc); 1085 EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooReferentVal)); 1086 }); 1087 } 1088 1089 TEST(TransferTest, PointerParamDecl) { 1090 std::string Code = R"( 1091 struct A {}; 1092 1093 void target(A *Foo) { 1094 (void)0; 1095 // [[p]] 1096 } 1097 )"; 1098 runDataflow( 1099 Code, 1100 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1101 ASTContext &ASTCtx) { 1102 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1103 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1104 1105 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1106 ASSERT_THAT(FooDecl, NotNull()); 1107 1108 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 1109 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 1110 1111 const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 1112 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 1113 EXPECT_TRUE(isa<RecordStorageLocation>(&FooPointeeLoc)); 1114 1115 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 1116 EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooPointeeVal)); 1117 }); 1118 } 1119 1120 TEST(TransferTest, StructMember) { 1121 std::string Code = R"( 1122 struct A { 1123 int Bar; 1124 }; 1125 1126 void target(A Foo) { 1127 int Baz = Foo.Bar; 1128 // [[p]] 1129 } 1130 )"; 1131 runDataflow( 1132 Code, 1133 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1134 ASTContext &ASTCtx) { 1135 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1136 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1137 1138 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1139 ASSERT_THAT(FooDecl, NotNull()); 1140 1141 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1142 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1143 1144 FieldDecl *BarDecl = nullptr; 1145 for (FieldDecl *Field : FooFields) { 1146 if (Field->getNameAsString() == "Bar") { 1147 BarDecl = Field; 1148 } else { 1149 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1150 } 1151 } 1152 ASSERT_THAT(BarDecl, NotNull()); 1153 1154 const auto *FooLoc = 1155 cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 1156 const auto *BarVal = 1157 cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)); 1158 1159 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1160 ASSERT_THAT(BazDecl, NotNull()); 1161 1162 EXPECT_EQ(Env.getValue(*BazDecl), BarVal); 1163 }); 1164 } 1165 1166 TEST(TransferTest, StructMemberEnum) { 1167 std::string Code = R"( 1168 struct A { 1169 int Bar; 1170 enum E { ONE, TWO }; 1171 }; 1172 1173 void target(A Foo) { 1174 A::E Baz = Foo.ONE; 1175 // [[p]] 1176 } 1177 )"; 1178 // Minimal expectations -- we're just testing that it doesn't crash, since 1179 // enums aren't interpreted. 1180 runDataflow( 1181 Code, 1182 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1183 ASTContext &ASTCtx) { 1184 EXPECT_THAT(Results.keys(), UnorderedElementsAre("p")); 1185 }); 1186 } 1187 1188 TEST(TransferTest, DerivedBaseMemberClass) { 1189 std::string Code = R"( 1190 class A { 1191 int ADefault; 1192 protected: 1193 int AProtected; 1194 private: 1195 int APrivate; 1196 public: 1197 int APublic; 1198 1199 private: 1200 friend void target(); 1201 }; 1202 1203 class B : public A { 1204 int BDefault; 1205 protected: 1206 int BProtected; 1207 private: 1208 int BPrivate; 1209 1210 private: 1211 friend void target(); 1212 }; 1213 1214 void target() { 1215 B Foo; 1216 (void)Foo.ADefault; 1217 (void)Foo.AProtected; 1218 (void)Foo.APrivate; 1219 (void)Foo.APublic; 1220 (void)Foo.BDefault; 1221 (void)Foo.BProtected; 1222 (void)Foo.BPrivate; 1223 // [[p]] 1224 } 1225 )"; 1226 runDataflow( 1227 Code, 1228 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1229 ASTContext &ASTCtx) { 1230 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1231 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1232 1233 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1234 ASSERT_THAT(FooDecl, NotNull()); 1235 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1236 1237 // Derived-class fields. 1238 const FieldDecl *BDefaultDecl = nullptr; 1239 const FieldDecl *BProtectedDecl = nullptr; 1240 const FieldDecl *BPrivateDecl = nullptr; 1241 for (const FieldDecl *Field : 1242 FooDecl->getType()->getAsRecordDecl()->fields()) { 1243 if (Field->getNameAsString() == "BDefault") { 1244 BDefaultDecl = Field; 1245 } else if (Field->getNameAsString() == "BProtected") { 1246 BProtectedDecl = Field; 1247 } else if (Field->getNameAsString() == "BPrivate") { 1248 BPrivateDecl = Field; 1249 } else { 1250 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1251 } 1252 } 1253 ASSERT_THAT(BDefaultDecl, NotNull()); 1254 ASSERT_THAT(BProtectedDecl, NotNull()); 1255 ASSERT_THAT(BPrivateDecl, NotNull()); 1256 1257 // Base-class fields. 1258 const FieldDecl *ADefaultDecl = nullptr; 1259 const FieldDecl *APrivateDecl = nullptr; 1260 const FieldDecl *AProtectedDecl = nullptr; 1261 const FieldDecl *APublicDecl = nullptr; 1262 for (const clang::CXXBaseSpecifier &Base : 1263 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1264 QualType BaseType = Base.getType(); 1265 ASSERT_TRUE(BaseType->isRecordType()); 1266 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1267 if (Field->getNameAsString() == "ADefault") { 1268 ADefaultDecl = Field; 1269 } else if (Field->getNameAsString() == "AProtected") { 1270 AProtectedDecl = Field; 1271 } else if (Field->getNameAsString() == "APrivate") { 1272 APrivateDecl = Field; 1273 } else if (Field->getNameAsString() == "APublic") { 1274 APublicDecl = Field; 1275 } else { 1276 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1277 } 1278 } 1279 } 1280 ASSERT_THAT(ADefaultDecl, NotNull()); 1281 ASSERT_THAT(AProtectedDecl, NotNull()); 1282 ASSERT_THAT(APrivateDecl, NotNull()); 1283 ASSERT_THAT(APublicDecl, NotNull()); 1284 1285 ASSERT_TRUE( 1286 isa<RecordStorageLocation>(Env.getStorageLocation(*FooDecl))); 1287 }); 1288 } 1289 1290 static void derivedBaseMemberExpectations( 1291 const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1292 ASTContext &ASTCtx) { 1293 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1294 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1295 1296 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1297 ASSERT_THAT(FooDecl, NotNull()); 1298 1299 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1300 const FieldDecl *BarDecl = nullptr; 1301 for (const clang::CXXBaseSpecifier &Base : 1302 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1303 QualType BaseType = Base.getType(); 1304 ASSERT_TRUE(BaseType->isStructureType()); 1305 1306 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1307 if (Field->getNameAsString() == "Bar") { 1308 BarDecl = Field; 1309 } else { 1310 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1311 } 1312 } 1313 } 1314 ASSERT_THAT(BarDecl, NotNull()); 1315 1316 const auto &FooLoc = 1317 *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 1318 const auto &FooVal = *cast<RecordValue>(Env.getValue(FooLoc)); 1319 EXPECT_EQ(&FooVal.getLoc(), &FooLoc); 1320 } 1321 1322 TEST(TransferTest, DerivedBaseMemberStructDefault) { 1323 std::string Code = R"( 1324 struct A { 1325 int Bar; 1326 }; 1327 struct B : public A { 1328 }; 1329 1330 void target() { 1331 B Foo; 1332 (void)Foo.Bar; 1333 // [[p]] 1334 } 1335 )"; 1336 runDataflow(Code, derivedBaseMemberExpectations); 1337 } 1338 1339 TEST(TransferTest, DerivedBaseMemberPrivateFriend) { 1340 // Include an access to `Foo.Bar` to verify the analysis doesn't crash on that 1341 // access. 1342 std::string Code = R"( 1343 struct A { 1344 private: 1345 friend void target(); 1346 int Bar; 1347 }; 1348 struct B : public A { 1349 }; 1350 1351 void target() { 1352 B Foo; 1353 (void)Foo.Bar; 1354 // [[p]] 1355 } 1356 )"; 1357 runDataflow(Code, derivedBaseMemberExpectations); 1358 } 1359 1360 TEST(TransferTest, ClassMember) { 1361 std::string Code = R"( 1362 class A { 1363 public: 1364 int Bar; 1365 }; 1366 1367 void target(A Foo) { 1368 int Baz = Foo.Bar; 1369 // [[p]] 1370 } 1371 )"; 1372 runDataflow( 1373 Code, 1374 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1375 ASTContext &ASTCtx) { 1376 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1377 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1378 1379 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1380 ASSERT_THAT(FooDecl, NotNull()); 1381 1382 ASSERT_TRUE(FooDecl->getType()->isClassType()); 1383 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1384 1385 FieldDecl *BarDecl = nullptr; 1386 for (FieldDecl *Field : FooFields) { 1387 if (Field->getNameAsString() == "Bar") { 1388 BarDecl = Field; 1389 } else { 1390 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1391 } 1392 } 1393 ASSERT_THAT(BarDecl, NotNull()); 1394 1395 const auto *FooLoc = 1396 cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 1397 const auto *BarVal = 1398 cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)); 1399 1400 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1401 ASSERT_THAT(BazDecl, NotNull()); 1402 1403 EXPECT_EQ(Env.getValue(*BazDecl), BarVal); 1404 }); 1405 } 1406 1407 TEST(TransferTest, BaseClassInitializer) { 1408 using ast_matchers::cxxConstructorDecl; 1409 using ast_matchers::hasName; 1410 using ast_matchers::ofClass; 1411 1412 std::string Code = R"( 1413 class A { 1414 public: 1415 A(int I) : Bar(I) {} 1416 int Bar; 1417 }; 1418 1419 class B : public A { 1420 public: 1421 B(int I) : A(I) { 1422 (void)0; 1423 // [[p]] 1424 } 1425 }; 1426 )"; 1427 ASSERT_THAT_ERROR( 1428 checkDataflow<NoopAnalysis>( 1429 AnalysisInputs<NoopAnalysis>( 1430 Code, cxxConstructorDecl(ofClass(hasName("B"))), 1431 [](ASTContext &C, Environment &) { return NoopAnalysis(C); }) 1432 .withASTBuildArgs( 1433 {"-fsyntax-only", "-fno-delayed-template-parsing", 1434 "-std=" + std::string(LangStandard::getLangStandardForKind( 1435 LangStandard::lang_cxx17) 1436 .getName())}), 1437 /*VerifyResults=*/ 1438 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1439 const AnalysisOutputs &) { 1440 // Regression test to verify that base-class initializers do not 1441 // trigger an assertion. If we add support for such initializers in 1442 // the future, we can expand this test to check more specific 1443 // properties. 1444 EXPECT_THAT(Results.keys(), UnorderedElementsAre("p")); 1445 }), 1446 llvm::Succeeded()); 1447 } 1448 1449 TEST(TransferTest, ReferenceMember) { 1450 std::string Code = R"( 1451 struct A { 1452 int &Bar; 1453 }; 1454 1455 void target(A Foo) { 1456 int Baz = Foo.Bar; 1457 // [[p]] 1458 } 1459 )"; 1460 runDataflow( 1461 Code, 1462 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1463 ASTContext &ASTCtx) { 1464 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1465 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1466 1467 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1468 ASSERT_THAT(FooDecl, NotNull()); 1469 1470 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1471 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1472 1473 FieldDecl *BarDecl = nullptr; 1474 for (FieldDecl *Field : FooFields) { 1475 if (Field->getNameAsString() == "Bar") { 1476 BarDecl = Field; 1477 } else { 1478 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1479 } 1480 } 1481 ASSERT_THAT(BarDecl, NotNull()); 1482 1483 const auto *FooLoc = 1484 cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 1485 const auto *BarReferentVal = 1486 cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)); 1487 1488 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1489 ASSERT_THAT(BazDecl, NotNull()); 1490 1491 EXPECT_EQ(Env.getValue(*BazDecl), BarReferentVal); 1492 }); 1493 } 1494 1495 TEST(TransferTest, StructThisMember) { 1496 std::string Code = R"( 1497 struct A { 1498 int Bar; 1499 1500 struct B { 1501 int Baz; 1502 }; 1503 1504 B Qux; 1505 1506 void target() { 1507 int Foo = Bar; 1508 int Quux = Qux.Baz; 1509 // [[p]] 1510 } 1511 }; 1512 )"; 1513 runDataflow( 1514 Code, 1515 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1516 ASTContext &ASTCtx) { 1517 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1518 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1519 1520 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1521 ASSERT_THAT(ThisLoc, NotNull()); 1522 1523 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1524 ASSERT_THAT(BarDecl, NotNull()); 1525 1526 const auto *BarLoc = 1527 cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl)); 1528 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1529 1530 const Value *BarVal = Env.getValue(*BarLoc); 1531 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1532 1533 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1534 ASSERT_THAT(FooDecl, NotNull()); 1535 EXPECT_EQ(Env.getValue(*FooDecl), BarVal); 1536 1537 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1538 ASSERT_THAT(QuxDecl, NotNull()); 1539 1540 ASSERT_TRUE(QuxDecl->getType()->isStructureType()); 1541 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1542 1543 FieldDecl *BazDecl = nullptr; 1544 for (FieldDecl *Field : QuxFields) { 1545 if (Field->getNameAsString() == "Baz") { 1546 BazDecl = Field; 1547 } else { 1548 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1549 } 1550 } 1551 ASSERT_THAT(BazDecl, NotNull()); 1552 1553 const auto *QuxLoc = 1554 cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl)); 1555 EXPECT_THAT(dyn_cast<RecordValue>(Env.getValue(*QuxLoc)), NotNull()); 1556 1557 const auto *BazVal = 1558 cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env)); 1559 1560 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1561 ASSERT_THAT(QuuxDecl, NotNull()); 1562 EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal); 1563 }); 1564 } 1565 1566 TEST(TransferTest, ClassThisMember) { 1567 std::string Code = R"( 1568 class A { 1569 int Bar; 1570 1571 class B { 1572 public: 1573 int Baz; 1574 }; 1575 1576 B Qux; 1577 1578 void target() { 1579 int Foo = Bar; 1580 int Quux = Qux.Baz; 1581 // [[p]] 1582 } 1583 }; 1584 )"; 1585 runDataflow( 1586 Code, 1587 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1588 ASTContext &ASTCtx) { 1589 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1590 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1591 1592 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1593 1594 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1595 ASSERT_THAT(BarDecl, NotNull()); 1596 1597 const auto *BarLoc = 1598 cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl)); 1599 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1600 1601 const Value *BarVal = Env.getValue(*BarLoc); 1602 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1603 1604 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1605 ASSERT_THAT(FooDecl, NotNull()); 1606 EXPECT_EQ(Env.getValue(*FooDecl), BarVal); 1607 1608 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1609 ASSERT_THAT(QuxDecl, NotNull()); 1610 1611 ASSERT_TRUE(QuxDecl->getType()->isClassType()); 1612 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1613 1614 FieldDecl *BazDecl = nullptr; 1615 for (FieldDecl *Field : QuxFields) { 1616 if (Field->getNameAsString() == "Baz") { 1617 BazDecl = Field; 1618 } else { 1619 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1620 } 1621 } 1622 ASSERT_THAT(BazDecl, NotNull()); 1623 1624 const auto *QuxLoc = 1625 cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl)); 1626 EXPECT_THAT(dyn_cast<RecordValue>(Env.getValue(*QuxLoc)), NotNull()); 1627 1628 const auto *BazVal = 1629 cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env)); 1630 1631 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1632 ASSERT_THAT(QuuxDecl, NotNull()); 1633 EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal); 1634 }); 1635 } 1636 1637 TEST(TransferTest, UnionThisMember) { 1638 std::string Code = R"( 1639 union A { 1640 int Foo; 1641 int Bar; 1642 1643 void target() { 1644 A a; 1645 // Mention the fields to ensure they're included in the analysis. 1646 (void)a.Foo; 1647 (void)a.Bar; 1648 // [[p]] 1649 } 1650 }; 1651 )"; 1652 runDataflow( 1653 Code, 1654 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1655 ASTContext &ASTCtx) { 1656 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1657 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1658 1659 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1660 ASSERT_THAT(ThisLoc, NotNull()); 1661 1662 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1663 ASSERT_THAT(FooDecl, NotNull()); 1664 1665 const auto *FooLoc = 1666 cast<ScalarStorageLocation>(ThisLoc->getChild(*FooDecl)); 1667 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 1668 1669 const Value *FooVal = Env.getValue(*FooLoc); 1670 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 1671 1672 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1673 ASSERT_THAT(BarDecl, NotNull()); 1674 1675 const auto *BarLoc = 1676 cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl)); 1677 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1678 1679 const Value *BarVal = Env.getValue(*BarLoc); 1680 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1681 }); 1682 } 1683 1684 TEST(TransferTest, StructThisInLambda) { 1685 std::string ThisCaptureCode = R"( 1686 struct A { 1687 void frob() { 1688 [this]() { 1689 int Foo = Bar; 1690 // [[p1]] 1691 }(); 1692 } 1693 1694 int Bar; 1695 }; 1696 )"; 1697 runDataflow( 1698 ThisCaptureCode, 1699 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1700 ASTContext &ASTCtx) { 1701 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1")); 1702 const Environment &Env = getEnvironmentAtAnnotation(Results, "p1"); 1703 1704 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1705 ASSERT_THAT(ThisLoc, NotNull()); 1706 1707 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1708 ASSERT_THAT(BarDecl, NotNull()); 1709 1710 const auto *BarLoc = 1711 cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl)); 1712 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1713 1714 const Value *BarVal = Env.getValue(*BarLoc); 1715 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1716 1717 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1718 ASSERT_THAT(FooDecl, NotNull()); 1719 EXPECT_EQ(Env.getValue(*FooDecl), BarVal); 1720 }, 1721 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1722 1723 std::string RefCaptureDefaultCode = R"( 1724 struct A { 1725 void frob() { 1726 [&]() { 1727 int Foo = Bar; 1728 // [[p2]] 1729 }(); 1730 } 1731 1732 int Bar; 1733 }; 1734 )"; 1735 runDataflow( 1736 RefCaptureDefaultCode, 1737 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1738 ASTContext &ASTCtx) { 1739 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2")); 1740 const Environment &Env = getEnvironmentAtAnnotation(Results, "p2"); 1741 1742 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1743 ASSERT_THAT(ThisLoc, NotNull()); 1744 1745 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1746 ASSERT_THAT(BarDecl, NotNull()); 1747 1748 const auto *BarLoc = 1749 cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl)); 1750 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1751 1752 const Value *BarVal = Env.getValue(*BarLoc); 1753 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1754 1755 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1756 ASSERT_THAT(FooDecl, NotNull()); 1757 EXPECT_EQ(Env.getValue(*FooDecl), BarVal); 1758 }, 1759 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1760 1761 std::string FreeFunctionLambdaCode = R"( 1762 void foo() { 1763 int Bar; 1764 [&]() { 1765 int Foo = Bar; 1766 // [[p3]] 1767 }(); 1768 } 1769 )"; 1770 runDataflow( 1771 FreeFunctionLambdaCode, 1772 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1773 ASTContext &ASTCtx) { 1774 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3")); 1775 const Environment &Env = getEnvironmentAtAnnotation(Results, "p3"); 1776 1777 EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull()); 1778 }, 1779 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1780 } 1781 1782 TEST(TransferTest, ConstructorInitializer) { 1783 std::string Code = R"( 1784 struct target { 1785 int Bar; 1786 1787 target(int Foo) : Bar(Foo) { 1788 int Qux = Bar; 1789 // [[p]] 1790 } 1791 }; 1792 )"; 1793 runDataflow( 1794 Code, 1795 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1796 ASTContext &ASTCtx) { 1797 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1798 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1799 1800 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1801 ASSERT_THAT(ThisLoc, NotNull()); 1802 1803 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1804 ASSERT_THAT(FooDecl, NotNull()); 1805 1806 const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl)); 1807 1808 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1809 ASSERT_THAT(QuxDecl, NotNull()); 1810 EXPECT_EQ(Env.getValue(*QuxDecl), FooVal); 1811 }); 1812 } 1813 1814 TEST(TransferTest, DefaultInitializer) { 1815 std::string Code = R"( 1816 struct target { 1817 int Bar; 1818 int Baz = Bar; 1819 1820 target(int Foo) : Bar(Foo) { 1821 int Qux = Baz; 1822 // [[p]] 1823 } 1824 }; 1825 )"; 1826 runDataflow( 1827 Code, 1828 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1829 ASTContext &ASTCtx) { 1830 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1831 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1832 1833 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1834 ASSERT_THAT(ThisLoc, NotNull()); 1835 1836 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1837 ASSERT_THAT(FooDecl, NotNull()); 1838 1839 const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl)); 1840 1841 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1842 ASSERT_THAT(QuxDecl, NotNull()); 1843 EXPECT_EQ(Env.getValue(*QuxDecl), FooVal); 1844 }); 1845 } 1846 1847 TEST(TransferTest, DefaultInitializerReference) { 1848 std::string Code = R"( 1849 struct target { 1850 int &Bar; 1851 int &Baz = Bar; 1852 1853 target(int &Foo) : Bar(Foo) { 1854 int &Qux = Baz; 1855 // [[p]] 1856 } 1857 }; 1858 )"; 1859 runDataflow( 1860 Code, 1861 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1862 ASTContext &ASTCtx) { 1863 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1864 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1865 1866 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1867 ASSERT_THAT(ThisLoc, NotNull()); 1868 1869 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1870 ASSERT_THAT(FooDecl, NotNull()); 1871 1872 const auto *FooLoc = Env.getStorageLocation(*FooDecl); 1873 1874 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1875 ASSERT_THAT(QuxDecl, NotNull()); 1876 1877 const auto *QuxLoc = Env.getStorageLocation(*QuxDecl); 1878 EXPECT_EQ(QuxLoc, FooLoc); 1879 }); 1880 } 1881 1882 TEST(TransferTest, TemporaryObject) { 1883 std::string Code = R"( 1884 struct A { 1885 int Bar; 1886 }; 1887 1888 void target() { 1889 A Foo = A(); 1890 (void)Foo.Bar; 1891 // [[p]] 1892 } 1893 )"; 1894 runDataflow( 1895 Code, 1896 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1897 ASTContext &ASTCtx) { 1898 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1899 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1900 1901 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1902 ASSERT_THAT(FooDecl, NotNull()); 1903 1904 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1905 ASSERT_THAT(BarDecl, NotNull()); 1906 1907 const auto *FooLoc = 1908 cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 1909 EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env))); 1910 }); 1911 } 1912 1913 TEST(TransferTest, ElidableConstructor) { 1914 // This test is effectively the same as TransferTest.TemporaryObject, but 1915 // the code is compiled as C++ 14. 1916 std::string Code = R"( 1917 struct A { 1918 int Bar; 1919 }; 1920 1921 void target() { 1922 A Foo = A(); 1923 (void)Foo.Bar; 1924 // [[p]] 1925 } 1926 )"; 1927 runDataflow( 1928 Code, 1929 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1930 ASTContext &ASTCtx) { 1931 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1932 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1933 1934 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1935 ASSERT_THAT(FooDecl, NotNull()); 1936 1937 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1938 ASSERT_THAT(BarDecl, NotNull()); 1939 1940 const auto *FooLoc = 1941 cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 1942 EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env))); 1943 }, 1944 LangStandard::lang_cxx14); 1945 } 1946 1947 TEST(TransferTest, AssignmentOperator) { 1948 std::string Code = R"( 1949 struct A { 1950 int Baz; 1951 }; 1952 1953 void target() { 1954 A Foo = { 1 }; 1955 A Bar = { 2 }; 1956 // [[p1]] 1957 Foo = Bar; 1958 // [[p2]] 1959 Foo.Baz = 3; 1960 // [[p3]] 1961 } 1962 )"; 1963 runDataflow( 1964 Code, 1965 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1966 ASTContext &ASTCtx) { 1967 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1968 ASSERT_THAT(FooDecl, NotNull()); 1969 1970 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1971 ASSERT_THAT(BarDecl, NotNull()); 1972 1973 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1974 ASSERT_THAT(BazDecl, NotNull()); 1975 1976 // Before copy assignment. 1977 { 1978 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 1979 1980 const auto *FooLoc1 = 1981 cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl)); 1982 const auto *BarLoc1 = 1983 cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl)); 1984 EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1)); 1985 1986 const auto *FooBazVal1 = 1987 cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1)); 1988 const auto *BarBazVal1 = 1989 cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1)); 1990 EXPECT_NE(FooBazVal1, BarBazVal1); 1991 } 1992 1993 // After copy assignment. 1994 { 1995 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 1996 1997 const auto *FooLoc2 = 1998 cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl)); 1999 const auto *BarLoc2 = 2000 cast<RecordStorageLocation>(Env2.getStorageLocation(*BarDecl)); 2001 2002 const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2)); 2003 const auto *BarVal2 = cast<RecordValue>(Env2.getValue(*BarLoc2)); 2004 EXPECT_NE(FooVal2, BarVal2); 2005 2006 EXPECT_TRUE(recordsEqual(*FooLoc2, *BarLoc2, Env2)); 2007 2008 const auto *FooBazVal2 = 2009 cast<IntegerValue>(getFieldValue(FooLoc2, *BazDecl, Env2)); 2010 const auto *BarBazVal2 = 2011 cast<IntegerValue>(getFieldValue(BarLoc2, *BazDecl, Env2)); 2012 EXPECT_EQ(FooBazVal2, BarBazVal2); 2013 } 2014 2015 // After value update. 2016 { 2017 const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3"); 2018 2019 const auto *FooLoc3 = 2020 cast<RecordStorageLocation>(Env3.getStorageLocation(*FooDecl)); 2021 const auto *BarLoc3 = 2022 cast<RecordStorageLocation>(Env3.getStorageLocation(*BarDecl)); 2023 EXPECT_FALSE(recordsEqual(*FooLoc3, *BarLoc3, Env3)); 2024 2025 const auto *FooBazVal3 = 2026 cast<IntegerValue>(getFieldValue(FooLoc3, *BazDecl, Env3)); 2027 const auto *BarBazVal3 = 2028 cast<IntegerValue>(getFieldValue(BarLoc3, *BazDecl, Env3)); 2029 EXPECT_NE(FooBazVal3, BarBazVal3); 2030 } 2031 }); 2032 } 2033 2034 TEST(TransferTest, AssignmentOperatorFromCallResult) { 2035 std::string Code = R"( 2036 struct A {}; 2037 A ReturnA(); 2038 2039 void target() { 2040 A MyA; 2041 MyA = ReturnA(); 2042 } 2043 )"; 2044 runDataflow( 2045 Code, 2046 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2047 ASTContext &ASTCtx) { 2048 // As of this writing, we don't produce a `Value` for the call 2049 // `ReturnA()`. The only condition we're testing for is that the 2050 // analysis should not crash in this case. 2051 }); 2052 } 2053 2054 TEST(TransferTest, CopyConstructor) { 2055 std::string Code = R"( 2056 struct A { 2057 int Baz; 2058 }; 2059 2060 void target() { 2061 A Foo = { 1 }; 2062 A Bar = Foo; 2063 // [[after_copy]] 2064 Foo.Baz = 2; 2065 // [[after_update]] 2066 } 2067 )"; 2068 runDataflow( 2069 Code, 2070 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2071 ASTContext &ASTCtx) { 2072 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2073 ASSERT_THAT(FooDecl, NotNull()); 2074 2075 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2076 ASSERT_THAT(BarDecl, NotNull()); 2077 2078 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2079 ASSERT_THAT(BazDecl, NotNull()); 2080 2081 // after_copy 2082 { 2083 const Environment &Env = 2084 getEnvironmentAtAnnotation(Results, "after_copy"); 2085 2086 const auto *FooLoc = 2087 cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 2088 const auto *BarLoc = 2089 cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl)); 2090 2091 // `Foo` and `Bar` have different `RecordValue`s associated with them. 2092 const auto *FooVal = cast<RecordValue>(Env.getValue(*FooLoc)); 2093 const auto *BarVal = cast<RecordValue>(Env.getValue(*BarLoc)); 2094 EXPECT_NE(FooVal, BarVal); 2095 2096 // But the records compare equal. 2097 EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env)); 2098 2099 // In particular, the value of `Baz` in both records is the same. 2100 const auto *FooBazVal = 2101 cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env)); 2102 const auto *BarBazVal = 2103 cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env)); 2104 EXPECT_EQ(FooBazVal, BarBazVal); 2105 } 2106 2107 // after_update 2108 { 2109 const Environment &Env = 2110 getEnvironmentAtAnnotation(Results, "after_update"); 2111 2112 const auto *FooLoc = 2113 cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 2114 const auto *BarLoc = 2115 cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl)); 2116 2117 EXPECT_FALSE(recordsEqual(*FooLoc, *BarLoc, Env)); 2118 2119 const auto *FooBazVal = 2120 cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env)); 2121 const auto *BarBazVal = 2122 cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env)); 2123 EXPECT_NE(FooBazVal, BarBazVal); 2124 } 2125 }); 2126 } 2127 2128 TEST(TransferTest, CopyConstructorWithDefaultArgument) { 2129 std::string Code = R"( 2130 struct A { 2131 int Baz; 2132 A() = default; 2133 A(const A& a, bool def = true) { Baz = a.Baz; } 2134 }; 2135 2136 void target() { 2137 A Foo; 2138 (void)Foo.Baz; 2139 A Bar = Foo; 2140 // [[p]] 2141 } 2142 )"; 2143 runDataflow( 2144 Code, 2145 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2146 ASTContext &ASTCtx) { 2147 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2148 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2149 2150 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2151 ASSERT_THAT(FooDecl, NotNull()); 2152 2153 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2154 ASSERT_THAT(BarDecl, NotNull()); 2155 2156 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2157 ASSERT_THAT(BazDecl, NotNull()); 2158 2159 const auto *FooLoc = 2160 cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 2161 const auto *BarLoc = 2162 cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl)); 2163 EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env)); 2164 2165 const auto *FooBazVal = 2166 cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env)); 2167 const auto *BarBazVal = 2168 cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env)); 2169 EXPECT_EQ(FooBazVal, BarBazVal); 2170 }); 2171 } 2172 2173 TEST(TransferTest, CopyConstructorWithParens) { 2174 std::string Code = R"( 2175 struct A { 2176 int Baz; 2177 }; 2178 2179 void target() { 2180 A Foo; 2181 (void)Foo.Baz; 2182 A Bar((A(Foo))); 2183 // [[p]] 2184 } 2185 )"; 2186 runDataflow( 2187 Code, 2188 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2189 ASTContext &ASTCtx) { 2190 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2191 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2192 2193 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2194 ASSERT_THAT(FooDecl, NotNull()); 2195 2196 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2197 ASSERT_THAT(BarDecl, NotNull()); 2198 2199 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2200 ASSERT_THAT(BazDecl, NotNull()); 2201 2202 const auto *FooLoc = 2203 cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)); 2204 const auto *BarLoc = 2205 cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl)); 2206 EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env)); 2207 2208 const auto *FooBazVal = 2209 cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env)); 2210 const auto *BarBazVal = 2211 cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env)); 2212 EXPECT_EQ(FooBazVal, BarBazVal); 2213 }); 2214 } 2215 2216 TEST(TransferTest, CopyConstructorWithInitializerListAsSyntacticSugar) { 2217 std::string Code = R"( 2218 struct A { 2219 int Baz; 2220 }; 2221 void target() { 2222 A Foo = {3}; 2223 (void)Foo.Baz; 2224 A Bar = {A(Foo)}; 2225 // [[p]] 2226 } 2227 )"; 2228 runDataflow( 2229 Code, 2230 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2231 ASTContext &ASTCtx) { 2232 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2233 2234 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2235 2236 const auto &FooLoc = 2237 getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo"); 2238 const auto &BarLoc = 2239 getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar"); 2240 2241 const auto *FooBazVal = 2242 cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env)); 2243 const auto *BarBazVal = 2244 cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env)); 2245 EXPECT_EQ(FooBazVal, BarBazVal); 2246 }); 2247 } 2248 2249 TEST(TransferTest, CopyConstructorArgIsRefReturnedByFunction) { 2250 // This is a crash repro. 2251 std::string Code = R"( 2252 struct S {}; 2253 const S &returnsSRef(); 2254 void target() { 2255 S s(returnsSRef()); 2256 } 2257 )"; 2258 runDataflow( 2259 Code, 2260 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2261 ASTContext &ASTCtx) {}); 2262 } 2263 2264 TEST(TransferTest, MoveConstructor) { 2265 std::string Code = R"( 2266 namespace std { 2267 2268 template <typename T> struct remove_reference { using type = T; }; 2269 template <typename T> struct remove_reference<T&> { using type = T; }; 2270 template <typename T> struct remove_reference<T&&> { using type = T; }; 2271 2272 template <typename T> 2273 using remove_reference_t = typename remove_reference<T>::type; 2274 2275 template <typename T> 2276 std::remove_reference_t<T>&& move(T&& x); 2277 2278 } // namespace std 2279 2280 struct A { 2281 int Baz; 2282 }; 2283 2284 void target() { 2285 A Foo; 2286 A Bar; 2287 (void)Foo.Baz; 2288 // [[p1]] 2289 Foo = std::move(Bar); 2290 // [[p2]] 2291 } 2292 )"; 2293 runDataflow( 2294 Code, 2295 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2296 ASTContext &ASTCtx) { 2297 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 2298 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 2299 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 2300 2301 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2302 ASSERT_THAT(FooDecl, NotNull()); 2303 2304 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2305 ASSERT_THAT(BarDecl, NotNull()); 2306 2307 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2308 ASSERT_THAT(BazDecl, NotNull()); 2309 2310 const auto *FooLoc1 = 2311 cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl)); 2312 const auto *BarLoc1 = 2313 cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl)); 2314 2315 EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1)); 2316 2317 const auto *FooVal1 = cast<RecordValue>(Env1.getValue(*FooLoc1)); 2318 const auto *BarVal1 = cast<RecordValue>(Env1.getValue(*BarLoc1)); 2319 EXPECT_NE(FooVal1, BarVal1); 2320 2321 const auto *FooBazVal1 = 2322 cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1)); 2323 const auto *BarBazVal1 = 2324 cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1)); 2325 EXPECT_NE(FooBazVal1, BarBazVal1); 2326 2327 const auto *FooLoc2 = 2328 cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl)); 2329 const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2)); 2330 EXPECT_NE(FooVal2, BarVal1); 2331 EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1)); 2332 2333 const auto *FooBazVal2 = 2334 cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env2)); 2335 EXPECT_EQ(FooBazVal2, BarBazVal1); 2336 }); 2337 } 2338 2339 TEST(TransferTest, BindTemporary) { 2340 std::string Code = R"( 2341 struct A { 2342 virtual ~A() = default; 2343 2344 int Baz; 2345 }; 2346 2347 void target(A Foo) { 2348 int Bar = A(Foo).Baz; 2349 // [[p]] 2350 } 2351 )"; 2352 runDataflow( 2353 Code, 2354 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2355 ASTContext &ASTCtx) { 2356 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2357 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2358 2359 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2360 ASSERT_THAT(FooDecl, NotNull()); 2361 2362 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2363 ASSERT_THAT(BarDecl, NotNull()); 2364 2365 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2366 ASSERT_THAT(BazDecl, NotNull()); 2367 2368 const auto &FooVal = *cast<RecordValue>(Env.getValue(*FooDecl)); 2369 const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 2370 EXPECT_EQ(BarVal, getFieldValue(&FooVal, *BazDecl, Env)); 2371 }); 2372 } 2373 2374 TEST(TransferTest, StaticCast) { 2375 std::string Code = R"( 2376 void target(int Foo) { 2377 int Bar = static_cast<int>(Foo); 2378 // [[p]] 2379 } 2380 )"; 2381 runDataflow( 2382 Code, 2383 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2384 ASTContext &ASTCtx) { 2385 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2386 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2387 2388 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2389 ASSERT_THAT(FooDecl, NotNull()); 2390 2391 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2392 ASSERT_THAT(BarDecl, NotNull()); 2393 2394 const auto *FooVal = Env.getValue(*FooDecl); 2395 const auto *BarVal = Env.getValue(*BarDecl); 2396 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2397 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2398 EXPECT_EQ(FooVal, BarVal); 2399 }); 2400 } 2401 2402 TEST(TransferTest, IntegralCast) { 2403 std::string Code = R"( 2404 void target(int Foo) { 2405 long Bar = Foo; 2406 // [[p]] 2407 } 2408 )"; 2409 runDataflow( 2410 Code, 2411 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2412 ASTContext &ASTCtx) { 2413 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2414 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2415 2416 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2417 ASSERT_THAT(FooDecl, NotNull()); 2418 2419 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2420 ASSERT_THAT(BarDecl, NotNull()); 2421 2422 const auto *FooVal = Env.getValue(*FooDecl); 2423 const auto *BarVal = Env.getValue(*BarDecl); 2424 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2425 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2426 EXPECT_EQ(FooVal, BarVal); 2427 }); 2428 } 2429 2430 TEST(TransferTest, IntegraltoBooleanCast) { 2431 std::string Code = R"( 2432 void target(int Foo) { 2433 bool Bar = Foo; 2434 // [[p]] 2435 } 2436 )"; 2437 runDataflow( 2438 Code, 2439 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2440 ASTContext &ASTCtx) { 2441 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2442 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2443 2444 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2445 ASSERT_THAT(FooDecl, NotNull()); 2446 2447 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2448 ASSERT_THAT(BarDecl, NotNull()); 2449 2450 const auto *FooVal = Env.getValue(*FooDecl); 2451 const auto *BarVal = Env.getValue(*BarDecl); 2452 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2453 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2454 }); 2455 } 2456 2457 TEST(TransferTest, IntegralToBooleanCastFromBool) { 2458 std::string Code = R"( 2459 void target(bool Foo) { 2460 int Zab = Foo; 2461 bool Bar = Zab; 2462 // [[p]] 2463 } 2464 )"; 2465 runDataflow( 2466 Code, 2467 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2468 ASTContext &ASTCtx) { 2469 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2470 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2471 2472 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2473 ASSERT_THAT(FooDecl, NotNull()); 2474 2475 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2476 ASSERT_THAT(BarDecl, NotNull()); 2477 2478 const auto *FooVal = Env.getValue(*FooDecl); 2479 const auto *BarVal = Env.getValue(*BarDecl); 2480 EXPECT_TRUE(isa<BoolValue>(FooVal)); 2481 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2482 EXPECT_EQ(FooVal, BarVal); 2483 }); 2484 } 2485 2486 TEST(TransferTest, NullToPointerCast) { 2487 std::string Code = R"( 2488 using my_nullptr_t = decltype(nullptr); 2489 struct Baz {}; 2490 void target() { 2491 int *FooX = nullptr; 2492 int *FooY = nullptr; 2493 bool **Bar = nullptr; 2494 Baz *Baz = nullptr; 2495 my_nullptr_t Null = 0; 2496 // [[p]] 2497 } 2498 )"; 2499 runDataflow( 2500 Code, 2501 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2502 ASTContext &ASTCtx) { 2503 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2504 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2505 2506 const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX"); 2507 ASSERT_THAT(FooXDecl, NotNull()); 2508 2509 const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY"); 2510 ASSERT_THAT(FooYDecl, NotNull()); 2511 2512 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2513 ASSERT_THAT(BarDecl, NotNull()); 2514 2515 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2516 ASSERT_THAT(BazDecl, NotNull()); 2517 2518 const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null"); 2519 ASSERT_THAT(NullDecl, NotNull()); 2520 2521 const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl)); 2522 const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl)); 2523 const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl)); 2524 const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl)); 2525 const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl)); 2526 2527 EXPECT_EQ(FooXVal, FooYVal); 2528 EXPECT_NE(FooXVal, BarVal); 2529 EXPECT_NE(FooXVal, BazVal); 2530 EXPECT_NE(BarVal, BazVal); 2531 2532 const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc(); 2533 EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc)); 2534 EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull()); 2535 2536 const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc(); 2537 EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc)); 2538 EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull()); 2539 2540 const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc(); 2541 EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc)); 2542 EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull()); 2543 2544 const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc(); 2545 EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc)); 2546 EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull()); 2547 }); 2548 } 2549 2550 TEST(TransferTest, PointerToMemberVariable) { 2551 std::string Code = R"( 2552 struct S { 2553 int i; 2554 }; 2555 void target() { 2556 int S::*MemberPointer = &S::i; 2557 // [[p]] 2558 } 2559 )"; 2560 runDataflow( 2561 Code, 2562 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2563 ASTContext &ASTCtx) { 2564 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2565 2566 const ValueDecl *MemberPointerDecl = 2567 findValueDecl(ASTCtx, "MemberPointer"); 2568 ASSERT_THAT(MemberPointerDecl, NotNull()); 2569 ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull()); 2570 }); 2571 } 2572 2573 TEST(TransferTest, PointerToMemberFunction) { 2574 std::string Code = R"( 2575 struct S { 2576 void Method(); 2577 }; 2578 void target() { 2579 void (S::*MemberPointer)() = &S::Method; 2580 // [[p]] 2581 } 2582 )"; 2583 runDataflow( 2584 Code, 2585 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2586 ASTContext &ASTCtx) { 2587 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2588 2589 const ValueDecl *MemberPointerDecl = 2590 findValueDecl(ASTCtx, "MemberPointer"); 2591 ASSERT_THAT(MemberPointerDecl, NotNull()); 2592 ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull()); 2593 }); 2594 } 2595 2596 TEST(TransferTest, NullToMemberPointerCast) { 2597 std::string Code = R"( 2598 struct Foo {}; 2599 void target() { 2600 int Foo::*MemberPointer = nullptr; 2601 // [[p]] 2602 } 2603 )"; 2604 runDataflow( 2605 Code, 2606 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2607 ASTContext &ASTCtx) { 2608 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2609 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2610 2611 const ValueDecl *MemberPointerDecl = 2612 findValueDecl(ASTCtx, "MemberPointer"); 2613 ASSERT_THAT(MemberPointerDecl, NotNull()); 2614 ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull()); 2615 }); 2616 } 2617 2618 TEST(TransferTest, AddrOfValue) { 2619 std::string Code = R"( 2620 void target() { 2621 int Foo; 2622 int *Bar = &Foo; 2623 // [[p]] 2624 } 2625 )"; 2626 runDataflow( 2627 Code, 2628 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2629 ASTContext &ASTCtx) { 2630 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2631 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2632 2633 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2634 ASSERT_THAT(FooDecl, NotNull()); 2635 2636 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2637 ASSERT_THAT(BarDecl, NotNull()); 2638 2639 const auto *FooLoc = 2640 cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl)); 2641 const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl)); 2642 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc); 2643 }); 2644 } 2645 2646 TEST(TransferTest, AddrOfReference) { 2647 std::string Code = R"( 2648 void target(int *Foo) { 2649 int *Bar = &(*Foo); 2650 // [[p]] 2651 } 2652 )"; 2653 runDataflow( 2654 Code, 2655 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2656 ASTContext &ASTCtx) { 2657 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2658 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2659 2660 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2661 ASSERT_THAT(FooDecl, NotNull()); 2662 2663 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2664 ASSERT_THAT(BarDecl, NotNull()); 2665 2666 const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl)); 2667 const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl)); 2668 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 2669 }); 2670 } 2671 2672 TEST(TransferTest, CannotAnalyzeFunctionTemplate) { 2673 std::string Code = R"( 2674 template <typename T> 2675 void target() {} 2676 )"; 2677 ASSERT_THAT_ERROR( 2678 checkDataflowWithNoopAnalysis(Code), 2679 llvm::FailedWithMessage("Cannot analyze templated declarations")); 2680 } 2681 2682 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) { 2683 std::string Code = R"( 2684 template <typename T> 2685 struct A { 2686 void target() {} 2687 }; 2688 )"; 2689 ASSERT_THAT_ERROR( 2690 checkDataflowWithNoopAnalysis(Code), 2691 llvm::FailedWithMessage("Cannot analyze templated declarations")); 2692 } 2693 2694 TEST(TransferTest, VarDeclInitAssignConditionalOperator) { 2695 std::string Code = R"( 2696 struct A {}; 2697 2698 void target(A Foo, A Bar, bool Cond) { 2699 A Baz = Cond ? Foo : Bar; 2700 /*[[p]]*/ 2701 } 2702 )"; 2703 runDataflow( 2704 Code, 2705 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2706 ASTContext &ASTCtx) { 2707 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2708 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2709 2710 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2711 ASSERT_THAT(FooDecl, NotNull()); 2712 2713 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2714 ASSERT_THAT(BarDecl, NotNull()); 2715 2716 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2717 ASSERT_THAT(BazDecl, NotNull()); 2718 2719 const auto *FooVal = cast<RecordValue>(Env.getValue(*FooDecl)); 2720 const auto *BarVal = cast<RecordValue>(Env.getValue(*BarDecl)); 2721 2722 const auto *BazVal = dyn_cast<RecordValue>(Env.getValue(*BazDecl)); 2723 ASSERT_THAT(BazVal, NotNull()); 2724 2725 EXPECT_NE(BazVal, FooVal); 2726 EXPECT_NE(BazVal, BarVal); 2727 }); 2728 } 2729 2730 TEST(TransferTest, VarDeclInDoWhile) { 2731 std::string Code = R"( 2732 void target(int *Foo) { 2733 do { 2734 int Bar = *Foo; 2735 // [[in_loop]] 2736 } while (false); 2737 (void)0; 2738 // [[after_loop]] 2739 } 2740 )"; 2741 runDataflow( 2742 Code, 2743 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2744 ASTContext &ASTCtx) { 2745 const Environment &EnvInLoop = 2746 getEnvironmentAtAnnotation(Results, "in_loop"); 2747 const Environment &EnvAfterLoop = 2748 getEnvironmentAtAnnotation(Results, "after_loop"); 2749 2750 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2751 ASSERT_THAT(FooDecl, NotNull()); 2752 2753 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2754 ASSERT_THAT(BarDecl, NotNull()); 2755 2756 const auto *FooVal = 2757 cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl)); 2758 const auto *FooPointeeVal = 2759 cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc())); 2760 2761 const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl)); 2762 EXPECT_EQ(BarVal, FooPointeeVal); 2763 2764 // FIXME: This assertion documents current behavior, but we would prefer 2765 // declarations to be removed from the environment when their lifetime 2766 // ends. Once this is the case, change this assertion accordingly. 2767 ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), BarVal); 2768 }); 2769 } 2770 2771 TEST(TransferTest, UnreachableAfterWhileTrue) { 2772 std::string Code = R"( 2773 void target() { 2774 while (true) {} 2775 (void)0; 2776 /*[[p]]*/ 2777 } 2778 )"; 2779 runDataflow( 2780 Code, 2781 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2782 ASTContext &ASTCtx) { 2783 // The node after the while-true is pruned because it is trivially 2784 // known to be unreachable. 2785 ASSERT_TRUE(Results.empty()); 2786 }); 2787 } 2788 2789 TEST(TransferTest, AggregateInitialization) { 2790 std::string BracesCode = R"( 2791 struct A { 2792 int Foo; 2793 }; 2794 2795 struct B { 2796 int Bar; 2797 A Baz; 2798 int Qux; 2799 }; 2800 2801 void target(int BarArg, int FooArg, int QuxArg) { 2802 B Quux{BarArg, {FooArg}, QuxArg}; 2803 B OtherB; 2804 /*[[p]]*/ 2805 } 2806 )"; 2807 std::string BraceElisionCode = R"( 2808 struct A { 2809 int Foo; 2810 }; 2811 2812 struct B { 2813 int Bar; 2814 A Baz; 2815 int Qux; 2816 }; 2817 2818 void target(int BarArg, int FooArg, int QuxArg) { 2819 B Quux = {BarArg, FooArg, QuxArg}; 2820 B OtherB; 2821 /*[[p]]*/ 2822 } 2823 )"; 2824 for (const std::string &Code : {BracesCode, BraceElisionCode}) { 2825 runDataflow( 2826 Code, 2827 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2828 ASTContext &ASTCtx) { 2829 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2830 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2831 2832 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2833 ASSERT_THAT(FooDecl, NotNull()); 2834 2835 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2836 ASSERT_THAT(BarDecl, NotNull()); 2837 2838 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2839 ASSERT_THAT(BazDecl, NotNull()); 2840 2841 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2842 ASSERT_THAT(QuxDecl, NotNull()); 2843 2844 const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg"); 2845 ASSERT_THAT(FooArgDecl, NotNull()); 2846 2847 const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg"); 2848 ASSERT_THAT(BarArgDecl, NotNull()); 2849 2850 const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg"); 2851 ASSERT_THAT(QuxArgDecl, NotNull()); 2852 2853 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 2854 ASSERT_THAT(QuuxDecl, NotNull()); 2855 2856 const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl)); 2857 const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl)); 2858 const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl)); 2859 2860 const auto *QuuxVal = cast<RecordValue>(Env.getValue(*QuuxDecl)); 2861 ASSERT_THAT(QuuxVal, NotNull()); 2862 2863 const auto *BazVal = 2864 cast<RecordValue>(getFieldValue(QuuxVal, *BazDecl, Env)); 2865 ASSERT_THAT(BazVal, NotNull()); 2866 2867 EXPECT_EQ(getFieldValue(QuuxVal, *BarDecl, Env), BarArgVal); 2868 EXPECT_EQ(getFieldValue(BazVal, *FooDecl, Env), FooArgVal); 2869 EXPECT_EQ(getFieldValue(QuuxVal, *QuxDecl, Env), QuxArgVal); 2870 2871 // Check that fields initialized in an initializer list are always 2872 // modeled in other instances of the same type. 2873 const auto &OtherBLoc = 2874 getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB"); 2875 EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull()); 2876 EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull()); 2877 EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull()); 2878 }); 2879 } 2880 } 2881 2882 TEST(TransferTest, AggregateInitializationReferenceField) { 2883 std::string Code = R"( 2884 struct S { 2885 int &RefField; 2886 }; 2887 2888 void target(int i) { 2889 S s = { i }; 2890 /*[[p]]*/ 2891 } 2892 )"; 2893 runDataflow( 2894 Code, 2895 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2896 ASTContext &ASTCtx) { 2897 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2898 2899 const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField"); 2900 2901 auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i"); 2902 auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"); 2903 2904 EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc); 2905 }); 2906 } 2907 2908 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) { 2909 std::string Code = R"( 2910 struct S { 2911 int i1; 2912 int i2; 2913 }; 2914 2915 void target(int i) { 2916 S s = { i }; 2917 /*[[p]]*/ 2918 } 2919 )"; 2920 runDataflow( 2921 Code, 2922 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2923 ASTContext &ASTCtx) { 2924 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2925 2926 const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1"); 2927 const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2"); 2928 2929 auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"); 2930 2931 auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i"); 2932 auto &I1Value = 2933 *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env)); 2934 EXPECT_EQ(&I1Value, &IValue); 2935 auto &I2Value = 2936 *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env)); 2937 EXPECT_NE(&I2Value, &IValue); 2938 }); 2939 } 2940 2941 TEST(TransferTest, AssignToUnionMember) { 2942 std::string Code = R"( 2943 union A { 2944 int Foo; 2945 }; 2946 2947 void target(int Bar) { 2948 A Baz; 2949 Baz.Foo = Bar; 2950 // [[p]] 2951 } 2952 )"; 2953 runDataflow( 2954 Code, 2955 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2956 ASTContext &ASTCtx) { 2957 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2958 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2959 2960 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2961 ASSERT_THAT(BazDecl, NotNull()); 2962 ASSERT_TRUE(BazDecl->getType()->isUnionType()); 2963 2964 auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields(); 2965 FieldDecl *FooDecl = nullptr; 2966 for (FieldDecl *Field : BazFields) { 2967 if (Field->getNameAsString() == "Foo") { 2968 FooDecl = Field; 2969 } else { 2970 FAIL() << "Unexpected field: " << Field->getNameAsString(); 2971 } 2972 } 2973 ASSERT_THAT(FooDecl, NotNull()); 2974 2975 const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>( 2976 Env.getStorageLocation(*BazDecl)); 2977 ASSERT_THAT(BazLoc, NotNull()); 2978 ASSERT_THAT(Env.getValue(*BazLoc), NotNull()); 2979 2980 const auto *FooVal = 2981 cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env)); 2982 2983 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2984 ASSERT_THAT(BarDecl, NotNull()); 2985 const auto *BarLoc = Env.getStorageLocation(*BarDecl); 2986 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 2987 2988 EXPECT_EQ(Env.getValue(*BarLoc), FooVal); 2989 }); 2990 } 2991 2992 TEST(TransferTest, AssignFromBoolLiteral) { 2993 std::string Code = R"( 2994 void target() { 2995 bool Foo = true; 2996 bool Bar = false; 2997 // [[p]] 2998 } 2999 )"; 3000 runDataflow( 3001 Code, 3002 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3003 ASTContext &ASTCtx) { 3004 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3005 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3006 3007 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3008 ASSERT_THAT(FooDecl, NotNull()); 3009 3010 const auto *FooVal = 3011 dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl)); 3012 ASSERT_THAT(FooVal, NotNull()); 3013 3014 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3015 ASSERT_THAT(BarDecl, NotNull()); 3016 3017 const auto *BarVal = 3018 dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*BarDecl)); 3019 ASSERT_THAT(BarVal, NotNull()); 3020 3021 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true)); 3022 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false)); 3023 }); 3024 } 3025 3026 TEST(TransferTest, AssignFromCompositeBoolExpression) { 3027 { 3028 std::string Code = R"( 3029 void target(bool Foo, bool Bar, bool Qux) { 3030 bool Baz = (Foo) && (Bar || Qux); 3031 // [[p]] 3032 } 3033 )"; 3034 runDataflow( 3035 Code, 3036 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3037 ASTContext &ASTCtx) { 3038 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3039 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3040 3041 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3042 ASSERT_THAT(FooDecl, NotNull()); 3043 3044 const auto *FooVal = 3045 dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl)); 3046 ASSERT_THAT(FooVal, NotNull()); 3047 3048 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3049 ASSERT_THAT(BarDecl, NotNull()); 3050 3051 const auto *BarVal = 3052 dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl)); 3053 ASSERT_THAT(BarVal, NotNull()); 3054 3055 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3056 ASSERT_THAT(QuxDecl, NotNull()); 3057 3058 const auto *QuxVal = 3059 dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl)); 3060 ASSERT_THAT(QuxVal, NotNull()); 3061 3062 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3063 ASSERT_THAT(BazDecl, NotNull()); 3064 3065 const auto *BazVal = 3066 dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl)); 3067 ASSERT_THAT(BazVal, NotNull()); 3068 auto &A = Env.arena(); 3069 EXPECT_EQ(&BazVal->formula(), 3070 &A.makeAnd(FooVal->formula(), 3071 A.makeOr(BarVal->formula(), QuxVal->formula()))); 3072 }); 3073 } 3074 3075 { 3076 std::string Code = R"( 3077 void target(bool Foo, bool Bar, bool Qux) { 3078 bool Baz = (Foo && Qux) || (Bar); 3079 // [[p]] 3080 } 3081 )"; 3082 runDataflow( 3083 Code, 3084 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3085 ASTContext &ASTCtx) { 3086 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3087 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3088 3089 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3090 ASSERT_THAT(FooDecl, NotNull()); 3091 3092 const auto *FooVal = 3093 dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl)); 3094 ASSERT_THAT(FooVal, NotNull()); 3095 3096 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3097 ASSERT_THAT(BarDecl, NotNull()); 3098 3099 const auto *BarVal = 3100 dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl)); 3101 ASSERT_THAT(BarVal, NotNull()); 3102 3103 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3104 ASSERT_THAT(QuxDecl, NotNull()); 3105 3106 const auto *QuxVal = 3107 dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl)); 3108 ASSERT_THAT(QuxVal, NotNull()); 3109 3110 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3111 ASSERT_THAT(BazDecl, NotNull()); 3112 3113 const auto *BazVal = 3114 dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl)); 3115 ASSERT_THAT(BazVal, NotNull()); 3116 auto &A = Env.arena(); 3117 EXPECT_EQ(&BazVal->formula(), 3118 &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()), 3119 BarVal->formula())); 3120 }); 3121 } 3122 3123 { 3124 std::string Code = R"( 3125 void target(bool A, bool B, bool C, bool D) { 3126 bool Foo = ((A && B) && C) && D; 3127 // [[p]] 3128 } 3129 )"; 3130 runDataflow( 3131 Code, 3132 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3133 ASTContext &ASTCtx) { 3134 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3135 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3136 3137 const ValueDecl *ADecl = findValueDecl(ASTCtx, "A"); 3138 ASSERT_THAT(ADecl, NotNull()); 3139 3140 const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl)); 3141 ASSERT_THAT(AVal, NotNull()); 3142 3143 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3144 ASSERT_THAT(BDecl, NotNull()); 3145 3146 const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl)); 3147 ASSERT_THAT(BVal, NotNull()); 3148 3149 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3150 ASSERT_THAT(CDecl, NotNull()); 3151 3152 const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl)); 3153 ASSERT_THAT(CVal, NotNull()); 3154 3155 const ValueDecl *DDecl = findValueDecl(ASTCtx, "D"); 3156 ASSERT_THAT(DDecl, NotNull()); 3157 3158 const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl)); 3159 ASSERT_THAT(DVal, NotNull()); 3160 3161 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3162 ASSERT_THAT(FooDecl, NotNull()); 3163 3164 const auto *FooVal = 3165 dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl)); 3166 ASSERT_THAT(FooVal, NotNull()); 3167 auto &A = Env.arena(); 3168 EXPECT_EQ( 3169 &FooVal->formula(), 3170 &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()), 3171 CVal->formula()), 3172 DVal->formula())); 3173 }); 3174 } 3175 } 3176 3177 TEST(TransferTest, AssignFromBoolNegation) { 3178 std::string Code = R"( 3179 void target() { 3180 bool Foo = true; 3181 bool Bar = !(Foo); 3182 // [[p]] 3183 } 3184 )"; 3185 runDataflow( 3186 Code, 3187 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3188 ASTContext &ASTCtx) { 3189 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3190 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3191 3192 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3193 ASSERT_THAT(FooDecl, NotNull()); 3194 3195 const auto *FooVal = 3196 dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl)); 3197 ASSERT_THAT(FooVal, NotNull()); 3198 3199 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3200 ASSERT_THAT(BarDecl, NotNull()); 3201 3202 const auto *BarVal = 3203 dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl)); 3204 ASSERT_THAT(BarVal, NotNull()); 3205 auto &A = Env.arena(); 3206 EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula())); 3207 }); 3208 } 3209 3210 TEST(TransferTest, BuiltinExpect) { 3211 std::string Code = R"( 3212 void target(long Foo) { 3213 long Bar = __builtin_expect(Foo, true); 3214 /*[[p]]*/ 3215 } 3216 )"; 3217 runDataflow( 3218 Code, 3219 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3220 ASTContext &ASTCtx) { 3221 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3222 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3223 3224 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3225 ASSERT_THAT(FooDecl, NotNull()); 3226 3227 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3228 ASSERT_THAT(BarDecl, NotNull()); 3229 3230 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3231 }); 3232 } 3233 3234 // `__builtin_expect` takes and returns a `long` argument, so other types 3235 // involve casts. This verifies that we identify the input and output in that 3236 // case. 3237 TEST(TransferTest, BuiltinExpectBoolArg) { 3238 std::string Code = R"( 3239 void target(bool Foo) { 3240 bool Bar = __builtin_expect(Foo, true); 3241 /*[[p]]*/ 3242 } 3243 )"; 3244 runDataflow( 3245 Code, 3246 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3247 ASTContext &ASTCtx) { 3248 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3249 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3250 3251 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3252 ASSERT_THAT(FooDecl, NotNull()); 3253 3254 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3255 ASSERT_THAT(BarDecl, NotNull()); 3256 3257 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3258 }); 3259 } 3260 3261 TEST(TransferTest, BuiltinUnreachable) { 3262 std::string Code = R"( 3263 void target(bool Foo) { 3264 bool Bar = false; 3265 if (Foo) 3266 Bar = Foo; 3267 else 3268 __builtin_unreachable(); 3269 (void)0; 3270 /*[[p]]*/ 3271 } 3272 )"; 3273 runDataflow( 3274 Code, 3275 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3276 ASTContext &ASTCtx) { 3277 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3278 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3279 3280 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3281 ASSERT_THAT(FooDecl, NotNull()); 3282 3283 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3284 ASSERT_THAT(BarDecl, NotNull()); 3285 3286 // `__builtin_unreachable` promises that the code is 3287 // unreachable, so the compiler treats the "then" branch as the 3288 // only possible predecessor of this statement. 3289 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3290 }); 3291 } 3292 3293 TEST(TransferTest, BuiltinTrap) { 3294 std::string Code = R"( 3295 void target(bool Foo) { 3296 bool Bar = false; 3297 if (Foo) 3298 Bar = Foo; 3299 else 3300 __builtin_trap(); 3301 (void)0; 3302 /*[[p]]*/ 3303 } 3304 )"; 3305 runDataflow( 3306 Code, 3307 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3308 ASTContext &ASTCtx) { 3309 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3310 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3311 3312 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3313 ASSERT_THAT(FooDecl, NotNull()); 3314 3315 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3316 ASSERT_THAT(BarDecl, NotNull()); 3317 3318 // `__builtin_trap` ensures program termination, so only the 3319 // "then" branch is a predecessor of this statement. 3320 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3321 }); 3322 } 3323 3324 TEST(TransferTest, BuiltinDebugTrap) { 3325 std::string Code = R"( 3326 void target(bool Foo) { 3327 bool Bar = false; 3328 if (Foo) 3329 Bar = Foo; 3330 else 3331 __builtin_debugtrap(); 3332 (void)0; 3333 /*[[p]]*/ 3334 } 3335 )"; 3336 runDataflow( 3337 Code, 3338 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3339 ASTContext &ASTCtx) { 3340 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3341 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3342 3343 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3344 ASSERT_THAT(FooDecl, NotNull()); 3345 3346 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3347 ASSERT_THAT(BarDecl, NotNull()); 3348 3349 // `__builtin_debugtrap` doesn't ensure program termination. 3350 EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3351 }); 3352 } 3353 3354 TEST(TransferTest, StaticIntSingleVarDecl) { 3355 std::string Code = R"( 3356 void target() { 3357 static int Foo; 3358 // [[p]] 3359 } 3360 )"; 3361 runDataflow( 3362 Code, 3363 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3364 ASTContext &ASTCtx) { 3365 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3366 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3367 3368 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3369 ASSERT_THAT(FooDecl, NotNull()); 3370 3371 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 3372 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3373 3374 const Value *FooVal = Env.getValue(*FooLoc); 3375 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3376 }); 3377 } 3378 3379 TEST(TransferTest, StaticIntGroupVarDecl) { 3380 std::string Code = R"( 3381 void target() { 3382 static int Foo, Bar; 3383 (void)0; 3384 // [[p]] 3385 } 3386 )"; 3387 runDataflow( 3388 Code, 3389 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3390 ASTContext &ASTCtx) { 3391 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3392 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3393 3394 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3395 ASSERT_THAT(FooDecl, NotNull()); 3396 3397 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3398 ASSERT_THAT(BarDecl, NotNull()); 3399 3400 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 3401 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3402 3403 const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl); 3404 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 3405 3406 const Value *FooVal = Env.getValue(*FooLoc); 3407 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3408 3409 const Value *BarVal = Env.getValue(*BarLoc); 3410 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 3411 3412 EXPECT_NE(FooVal, BarVal); 3413 }); 3414 } 3415 3416 TEST(TransferTest, GlobalIntVarDecl) { 3417 std::string Code = R"( 3418 static int Foo; 3419 3420 void target() { 3421 int Bar = Foo; 3422 int Baz = Foo; 3423 // [[p]] 3424 } 3425 )"; 3426 runDataflow( 3427 Code, 3428 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3429 ASTContext &ASTCtx) { 3430 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3431 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3432 3433 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3434 ASSERT_THAT(BarDecl, NotNull()); 3435 3436 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3437 ASSERT_THAT(BazDecl, NotNull()); 3438 3439 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3440 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3441 EXPECT_EQ(BarVal, BazVal); 3442 }); 3443 } 3444 3445 TEST(TransferTest, StaticMemberIntVarDecl) { 3446 std::string Code = R"( 3447 struct A { 3448 static int Foo; 3449 }; 3450 3451 void target(A a) { 3452 int Bar = a.Foo; 3453 int Baz = a.Foo; 3454 // [[p]] 3455 } 3456 )"; 3457 runDataflow( 3458 Code, 3459 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3460 ASTContext &ASTCtx) { 3461 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3462 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3463 3464 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3465 ASSERT_THAT(BarDecl, NotNull()); 3466 3467 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3468 ASSERT_THAT(BazDecl, NotNull()); 3469 3470 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3471 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3472 EXPECT_EQ(BarVal, BazVal); 3473 }); 3474 } 3475 3476 TEST(TransferTest, StaticMemberRefVarDecl) { 3477 std::string Code = R"( 3478 struct A { 3479 static int &Foo; 3480 }; 3481 3482 void target(A a) { 3483 int Bar = a.Foo; 3484 int Baz = a.Foo; 3485 // [[p]] 3486 } 3487 )"; 3488 runDataflow( 3489 Code, 3490 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3491 ASTContext &ASTCtx) { 3492 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3493 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3494 3495 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3496 ASSERT_THAT(BarDecl, NotNull()); 3497 3498 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3499 ASSERT_THAT(BazDecl, NotNull()); 3500 3501 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3502 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3503 EXPECT_EQ(BarVal, BazVal); 3504 }); 3505 } 3506 3507 TEST(TransferTest, AssignMemberBeforeCopy) { 3508 std::string Code = R"( 3509 struct A { 3510 int Foo; 3511 }; 3512 3513 void target() { 3514 A A1; 3515 A A2; 3516 int Bar; 3517 A1.Foo = Bar; 3518 A2 = A1; 3519 // [[p]] 3520 } 3521 )"; 3522 runDataflow( 3523 Code, 3524 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3525 ASTContext &ASTCtx) { 3526 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3527 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3528 3529 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3530 ASSERT_THAT(FooDecl, NotNull()); 3531 3532 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3533 ASSERT_THAT(BarDecl, NotNull()); 3534 3535 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); 3536 ASSERT_THAT(A1Decl, NotNull()); 3537 3538 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); 3539 ASSERT_THAT(A2Decl, NotNull()); 3540 3541 const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3542 3543 const auto *A2Val = cast<RecordValue>(Env.getValue(*A2Decl)); 3544 EXPECT_EQ(getFieldValue(A2Val, *FooDecl, Env), BarVal); 3545 }); 3546 } 3547 3548 TEST(TransferTest, BooleanEquality) { 3549 std::string Code = R"( 3550 void target(bool Bar) { 3551 bool Foo = true; 3552 if (Bar == Foo) { 3553 (void)0; 3554 /*[[p-then]]*/ 3555 } else { 3556 (void)0; 3557 /*[[p-else]]*/ 3558 } 3559 } 3560 )"; 3561 runDataflow( 3562 Code, 3563 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3564 ASTContext &ASTCtx) { 3565 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else")); 3566 const Environment &EnvThen = 3567 getEnvironmentAtAnnotation(Results, "p-then"); 3568 const Environment &EnvElse = 3569 getEnvironmentAtAnnotation(Results, "p-else"); 3570 3571 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3572 ASSERT_THAT(BarDecl, NotNull()); 3573 3574 auto &BarValThen = getFormula(*BarDecl, EnvThen); 3575 EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen)); 3576 3577 auto &BarValElse = getFormula(*BarDecl, EnvElse); 3578 EXPECT_TRUE( 3579 EnvElse.flowConditionImplies(EnvElse.arena().makeNot(BarValElse))); 3580 }); 3581 } 3582 3583 TEST(TransferTest, BooleanInequality) { 3584 std::string Code = R"( 3585 void target(bool Bar) { 3586 bool Foo = true; 3587 if (Bar != Foo) { 3588 (void)0; 3589 /*[[p-then]]*/ 3590 } else { 3591 (void)0; 3592 /*[[p-else]]*/ 3593 } 3594 } 3595 )"; 3596 runDataflow( 3597 Code, 3598 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3599 ASTContext &ASTCtx) { 3600 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else")); 3601 const Environment &EnvThen = 3602 getEnvironmentAtAnnotation(Results, "p-then"); 3603 const Environment &EnvElse = 3604 getEnvironmentAtAnnotation(Results, "p-else"); 3605 3606 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3607 ASSERT_THAT(BarDecl, NotNull()); 3608 3609 auto &BarValThen = getFormula(*BarDecl, EnvThen); 3610 EXPECT_TRUE( 3611 EnvThen.flowConditionImplies(EnvThen.arena().makeNot(BarValThen))); 3612 3613 auto &BarValElse = getFormula(*BarDecl, EnvElse); 3614 EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse)); 3615 }); 3616 } 3617 3618 TEST(TransferTest, IntegerLiteralEquality) { 3619 std::string Code = R"( 3620 void target() { 3621 bool equal = (42 == 42); 3622 // [[p]] 3623 } 3624 )"; 3625 runDataflow( 3626 Code, 3627 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3628 ASTContext &ASTCtx) { 3629 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3630 3631 auto &Equal = 3632 getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula(); 3633 EXPECT_TRUE(Env.flowConditionImplies(Equal)); 3634 }); 3635 } 3636 3637 TEST(TransferTest, CorrelatedBranches) { 3638 std::string Code = R"( 3639 void target(bool B, bool C) { 3640 if (B) { 3641 return; 3642 } 3643 (void)0; 3644 /*[[p0]]*/ 3645 if (C) { 3646 B = true; 3647 /*[[p1]]*/ 3648 } 3649 if (B) { 3650 (void)0; 3651 /*[[p2]]*/ 3652 } 3653 } 3654 )"; 3655 runDataflow( 3656 Code, 3657 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3658 ASTContext &ASTCtx) { 3659 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2")); 3660 3661 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3662 ASSERT_THAT(CDecl, NotNull()); 3663 3664 { 3665 const Environment &Env = getEnvironmentAtAnnotation(Results, "p0"); 3666 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3667 ASSERT_THAT(BDecl, NotNull()); 3668 auto &BVal = getFormula(*BDecl, Env); 3669 3670 EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BVal))); 3671 } 3672 3673 { 3674 const Environment &Env = getEnvironmentAtAnnotation(Results, "p1"); 3675 auto &CVal = getFormula(*CDecl, Env); 3676 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3677 } 3678 3679 { 3680 const Environment &Env = getEnvironmentAtAnnotation(Results, "p2"); 3681 auto &CVal = getFormula(*CDecl, Env); 3682 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3683 } 3684 }); 3685 } 3686 3687 TEST(TransferTest, LoopWithAssignmentConverges) { 3688 std::string Code = R"( 3689 bool foo(); 3690 3691 void target() { 3692 do { 3693 bool Bar = foo(); 3694 if (Bar) break; 3695 (void)Bar; 3696 /*[[p]]*/ 3697 } while (true); 3698 } 3699 )"; 3700 // The key property that we are verifying is implicit in `runDataflow` -- 3701 // namely, that the analysis succeeds, rather than hitting the maximum number 3702 // of iterations. 3703 runDataflow( 3704 Code, 3705 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3706 ASTContext &ASTCtx) { 3707 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3708 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3709 3710 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3711 ASSERT_THAT(BarDecl, NotNull()); 3712 3713 auto &BarVal = getFormula(*BarDecl, Env); 3714 EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal))); 3715 }); 3716 } 3717 3718 TEST(TransferTest, LoopWithStagedAssignments) { 3719 std::string Code = R"( 3720 bool foo(); 3721 3722 void target() { 3723 bool Bar = false; 3724 bool Err = false; 3725 while (foo()) { 3726 if (Bar) 3727 Err = true; 3728 Bar = true; 3729 /*[[p]]*/ 3730 } 3731 } 3732 )"; 3733 runDataflow( 3734 Code, 3735 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3736 ASTContext &ASTCtx) { 3737 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3738 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3739 3740 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3741 ASSERT_THAT(BarDecl, NotNull()); 3742 const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err"); 3743 ASSERT_THAT(ErrDecl, NotNull()); 3744 3745 auto &BarVal = getFormula(*BarDecl, Env); 3746 auto &ErrVal = getFormula(*ErrDecl, Env); 3747 EXPECT_TRUE(Env.flowConditionImplies(BarVal)); 3748 // An unsound analysis, for example only evaluating the loop once, can 3749 // conclude that `Err` is false. So, we test that this conclusion is not 3750 // reached. 3751 EXPECT_FALSE( 3752 Env.flowConditionImplies(Env.arena().makeNot(ErrVal))); 3753 }); 3754 } 3755 3756 TEST(TransferTest, LoopWithReferenceAssignmentConverges) { 3757 std::string Code = R"( 3758 bool &foo(); 3759 3760 void target() { 3761 do { 3762 bool& Bar = foo(); 3763 if (Bar) break; 3764 (void)Bar; 3765 /*[[p]]*/ 3766 } while (true); 3767 } 3768 )"; 3769 // The key property that we are verifying is that the analysis succeeds, 3770 // rather than hitting the maximum number of iterations. 3771 runDataflow( 3772 Code, 3773 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3774 ASTContext &ASTCtx) { 3775 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3776 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3777 3778 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3779 ASSERT_THAT(BarDecl, NotNull()); 3780 3781 auto &BarVal = getFormula(*BarDecl, Env); 3782 EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal))); 3783 }); 3784 } 3785 3786 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) { 3787 std::string Code = R"( 3788 struct Lookup { 3789 int x; 3790 }; 3791 3792 void target(Lookup val, bool b) { 3793 const Lookup* l = nullptr; 3794 while (b) { 3795 l = &val; 3796 /*[[p-inner]]*/ 3797 } 3798 (void)0; 3799 /*[[p-outer]]*/ 3800 } 3801 )"; 3802 // The key property that we are verifying is implicit in `runDataflow` -- 3803 // namely, that the analysis succeeds, rather than hitting the maximum number 3804 // of iterations. 3805 runDataflow( 3806 Code, 3807 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3808 ASTContext &ASTCtx) { 3809 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer")); 3810 const Environment &InnerEnv = 3811 getEnvironmentAtAnnotation(Results, "p-inner"); 3812 const Environment &OuterEnv = 3813 getEnvironmentAtAnnotation(Results, "p-outer"); 3814 3815 const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val"); 3816 ASSERT_THAT(ValDecl, NotNull()); 3817 3818 const ValueDecl *LDecl = findValueDecl(ASTCtx, "l"); 3819 ASSERT_THAT(LDecl, NotNull()); 3820 3821 // Inner. 3822 auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl)); 3823 ASSERT_THAT(LVal, NotNull()); 3824 3825 EXPECT_EQ(&LVal->getPointeeLoc(), 3826 InnerEnv.getStorageLocation(*ValDecl)); 3827 3828 // Outer. 3829 LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl)); 3830 ASSERT_THAT(LVal, NotNull()); 3831 3832 // The loop body may not have been executed, so we should not conclude 3833 // that `l` points to `val`. 3834 EXPECT_NE(&LVal->getPointeeLoc(), 3835 OuterEnv.getStorageLocation(*ValDecl)); 3836 }); 3837 } 3838 3839 TEST(TransferTest, LoopDereferencingChangingPointerConverges) { 3840 std::string Code = R"cc( 3841 bool some_condition(); 3842 3843 void target(int i1, int i2) { 3844 int *p = &i1; 3845 while (true) { 3846 (void)*p; 3847 if (some_condition()) 3848 p = &i1; 3849 else 3850 p = &i2; 3851 } 3852 } 3853 )cc"; 3854 // FIXME: Implement pointer value widening to make analysis converge. 3855 ASSERT_THAT_ERROR( 3856 checkDataflowWithNoopAnalysis(Code), 3857 llvm::FailedWithMessage("maximum number of iterations reached")); 3858 } 3859 3860 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) { 3861 std::string Code = R"cc( 3862 struct Lookup { 3863 int x; 3864 }; 3865 3866 bool some_condition(); 3867 3868 void target(Lookup l1, Lookup l2) { 3869 Lookup *l = &l1; 3870 while (true) { 3871 (void)l->x; 3872 if (some_condition()) 3873 l = &l1; 3874 else 3875 l = &l2; 3876 } 3877 } 3878 )cc"; 3879 // FIXME: Implement pointer value widening to make analysis converge. 3880 ASSERT_THAT_ERROR( 3881 checkDataflowWithNoopAnalysis(Code), 3882 llvm::FailedWithMessage("maximum number of iterations reached")); 3883 } 3884 3885 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { 3886 std::string Code = R"( 3887 union Union { 3888 int A; 3889 float B; 3890 }; 3891 3892 void foo() { 3893 Union A; 3894 Union B; 3895 A = B; 3896 } 3897 )"; 3898 // This is a crash regression test when calling the transfer function on a 3899 // `CXXThisExpr` that refers to a union. 3900 runDataflow( 3901 Code, 3902 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &, 3903 ASTContext &) {}, 3904 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator="); 3905 } 3906 3907 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) { 3908 std::string Code = R"( 3909 struct A { 3910 int Foo; 3911 int Bar; 3912 }; 3913 3914 void target() { 3915 int Qux; 3916 A Baz; 3917 Baz.Foo = Qux; 3918 auto &FooRef = Baz.Foo; 3919 auto &BarRef = Baz.Bar; 3920 auto &[BoundFooRef, BoundBarRef] = Baz; 3921 // [[p]] 3922 } 3923 )"; 3924 runDataflow( 3925 Code, 3926 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3927 ASTContext &ASTCtx) { 3928 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3929 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3930 3931 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3932 ASSERT_THAT(FooRefDecl, NotNull()); 3933 3934 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3935 ASSERT_THAT(BarRefDecl, NotNull()); 3936 3937 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3938 ASSERT_THAT(QuxDecl, NotNull()); 3939 3940 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3941 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3942 3943 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3944 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3945 3946 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 3947 ASSERT_THAT(FooRefLoc, NotNull()); 3948 3949 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 3950 ASSERT_THAT(BarRefLoc, NotNull()); 3951 3952 const Value *QuxVal = Env.getValue(*QuxDecl); 3953 ASSERT_THAT(QuxVal, NotNull()); 3954 3955 const StorageLocation *BoundFooRefLoc = 3956 Env.getStorageLocation(*BoundFooRefDecl); 3957 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3958 3959 const StorageLocation *BoundBarRefLoc = 3960 Env.getStorageLocation(*BoundBarRefDecl); 3961 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3962 3963 EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal); 3964 }); 3965 } 3966 3967 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) { 3968 std::string Code = R"( 3969 struct A { 3970 int &Foo; 3971 int &Bar; 3972 }; 3973 3974 void target(A Baz) { 3975 int Qux; 3976 Baz.Foo = Qux; 3977 auto &FooRef = Baz.Foo; 3978 auto &BarRef = Baz.Bar; 3979 auto &[BoundFooRef, BoundBarRef] = Baz; 3980 // [[p]] 3981 } 3982 )"; 3983 runDataflow( 3984 Code, 3985 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3986 ASTContext &ASTCtx) { 3987 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3988 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3989 3990 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3991 ASSERT_THAT(FooRefDecl, NotNull()); 3992 3993 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3994 ASSERT_THAT(BarRefDecl, NotNull()); 3995 3996 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3997 ASSERT_THAT(QuxDecl, NotNull()); 3998 3999 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 4000 ASSERT_THAT(BoundFooRefDecl, NotNull()); 4001 4002 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 4003 ASSERT_THAT(BoundBarRefDecl, NotNull()); 4004 4005 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 4006 ASSERT_THAT(FooRefLoc, NotNull()); 4007 4008 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 4009 ASSERT_THAT(BarRefLoc, NotNull()); 4010 4011 const Value *QuxVal = Env.getValue(*QuxDecl); 4012 ASSERT_THAT(QuxVal, NotNull()); 4013 4014 const StorageLocation *BoundFooRefLoc = 4015 Env.getStorageLocation(*BoundFooRefDecl); 4016 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 4017 4018 const StorageLocation *BoundBarRefLoc = 4019 Env.getStorageLocation(*BoundBarRefDecl); 4020 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 4021 4022 EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal); 4023 }); 4024 } 4025 4026 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) { 4027 std::string Code = R"( 4028 struct A { 4029 int Foo; 4030 int Bar; 4031 }; 4032 4033 void target() { 4034 int Qux; 4035 A Baz; 4036 Baz.Foo = Qux; 4037 auto &FooRef = Baz.Foo; 4038 auto &BarRef = Baz.Bar; 4039 auto [BoundFoo, BoundBar] = Baz; 4040 // [[p]] 4041 } 4042 )"; 4043 runDataflow( 4044 Code, 4045 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4046 ASTContext &ASTCtx) { 4047 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4048 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4049 4050 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 4051 ASSERT_THAT(FooRefDecl, NotNull()); 4052 4053 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 4054 ASSERT_THAT(BarRefDecl, NotNull()); 4055 4056 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 4057 ASSERT_THAT(BoundFooDecl, NotNull()); 4058 4059 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 4060 ASSERT_THAT(BoundBarDecl, NotNull()); 4061 4062 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 4063 ASSERT_THAT(QuxDecl, NotNull()); 4064 4065 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 4066 ASSERT_THAT(FooRefLoc, NotNull()); 4067 4068 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 4069 ASSERT_THAT(BarRefLoc, NotNull()); 4070 4071 const Value *QuxVal = Env.getValue(*QuxDecl); 4072 ASSERT_THAT(QuxVal, NotNull()); 4073 4074 const StorageLocation *BoundFooLoc = 4075 Env.getStorageLocation(*BoundFooDecl); 4076 EXPECT_NE(BoundFooLoc, FooRefLoc); 4077 4078 const StorageLocation *BoundBarLoc = 4079 Env.getStorageLocation(*BoundBarDecl); 4080 EXPECT_NE(BoundBarLoc, BarRefLoc); 4081 4082 EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal); 4083 }); 4084 } 4085 4086 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) { 4087 std::string Code = R"( 4088 namespace std { 4089 using size_t = int; 4090 template <class> struct tuple_size; 4091 template <std::size_t, class> struct tuple_element; 4092 template <class...> class tuple; 4093 4094 namespace { 4095 template <class T, T v> 4096 struct size_helper { static const T value = v; }; 4097 } // namespace 4098 4099 template <class... T> 4100 struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {}; 4101 4102 template <std::size_t I, class... T> 4103 struct tuple_element<I, tuple<T...>> { 4104 using type = __type_pack_element<I, T...>; 4105 }; 4106 4107 template <class...> class tuple {}; 4108 4109 template <std::size_t I, class... T> 4110 typename tuple_element<I, tuple<T...>>::type get(tuple<T...>); 4111 } // namespace std 4112 4113 std::tuple<bool, int> makeTuple(); 4114 4115 void target(bool B) { 4116 auto [BoundFoo, BoundBar] = makeTuple(); 4117 bool Baz; 4118 // Include if-then-else to test interaction of `BindingDecl` with join. 4119 if (B) { 4120 Baz = BoundFoo; 4121 (void)BoundBar; 4122 // [[p1]] 4123 } else { 4124 Baz = BoundFoo; 4125 } 4126 (void)0; 4127 // [[p2]] 4128 } 4129 )"; 4130 runDataflow( 4131 Code, 4132 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4133 ASTContext &ASTCtx) { 4134 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 4135 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 4136 4137 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 4138 ASSERT_THAT(BoundFooDecl, NotNull()); 4139 4140 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 4141 ASSERT_THAT(BoundBarDecl, NotNull()); 4142 4143 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4144 ASSERT_THAT(BazDecl, NotNull()); 4145 4146 // BindingDecls always map to references -- either lvalue or rvalue, so 4147 // we still need to skip here. 4148 const Value *BoundFooValue = Env1.getValue(*BoundFooDecl); 4149 ASSERT_THAT(BoundFooValue, NotNull()); 4150 EXPECT_TRUE(isa<BoolValue>(BoundFooValue)); 4151 4152 const Value *BoundBarValue = Env1.getValue(*BoundBarDecl); 4153 ASSERT_THAT(BoundBarValue, NotNull()); 4154 EXPECT_TRUE(isa<IntegerValue>(BoundBarValue)); 4155 4156 // Test that a `DeclRefExpr` to a `BindingDecl` works as expected. 4157 EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue); 4158 4159 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 4160 4161 // Test that `BoundFooDecl` retains the value we expect, after the join. 4162 BoundFooValue = Env2.getValue(*BoundFooDecl); 4163 EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue); 4164 }); 4165 } 4166 4167 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) { 4168 std::string Code = R"( 4169 namespace std { 4170 using size_t = int; 4171 template <class> struct tuple_size; 4172 template <std::size_t, class> struct tuple_element; 4173 template <class...> class tuple; 4174 4175 namespace { 4176 template <class T, T v> 4177 struct size_helper { static const T value = v; }; 4178 } // namespace 4179 4180 template <class... T> 4181 struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {}; 4182 4183 template <std::size_t I, class... T> 4184 struct tuple_element<I, tuple<T...>> { 4185 using type = __type_pack_element<I, T...>; 4186 }; 4187 4188 template <class...> class tuple {}; 4189 4190 template <std::size_t I, class... T> 4191 typename tuple_element<I, tuple<T...>>::type get(tuple<T...>); 4192 } // namespace std 4193 4194 std::tuple<bool, int> &getTuple(); 4195 4196 void target(bool B) { 4197 auto &[BoundFoo, BoundBar] = getTuple(); 4198 bool Baz; 4199 // Include if-then-else to test interaction of `BindingDecl` with join. 4200 if (B) { 4201 Baz = BoundFoo; 4202 (void)BoundBar; 4203 // [[p1]] 4204 } else { 4205 Baz = BoundFoo; 4206 } 4207 (void)0; 4208 // [[p2]] 4209 } 4210 )"; 4211 runDataflow( 4212 Code, 4213 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4214 ASTContext &ASTCtx) { 4215 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 4216 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 4217 4218 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 4219 ASSERT_THAT(BoundFooDecl, NotNull()); 4220 4221 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 4222 ASSERT_THAT(BoundBarDecl, NotNull()); 4223 4224 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4225 ASSERT_THAT(BazDecl, NotNull()); 4226 4227 const Value *BoundFooValue = Env1.getValue(*BoundFooDecl); 4228 ASSERT_THAT(BoundFooValue, NotNull()); 4229 EXPECT_TRUE(isa<BoolValue>(BoundFooValue)); 4230 4231 const Value *BoundBarValue = Env1.getValue(*BoundBarDecl); 4232 ASSERT_THAT(BoundBarValue, NotNull()); 4233 EXPECT_TRUE(isa<IntegerValue>(BoundBarValue)); 4234 4235 // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type) 4236 // works as expected. We don't test aliasing properties of the 4237 // reference, because we don't model `std::get` and so have no way to 4238 // equate separate references into the tuple. 4239 EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue); 4240 4241 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 4242 4243 // Test that `BoundFooDecl` retains the value we expect, after the join. 4244 BoundFooValue = Env2.getValue(*BoundFooDecl); 4245 EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue); 4246 }); 4247 } 4248 4249 TEST(TransferTest, BinaryOperatorComma) { 4250 std::string Code = R"( 4251 void target(int Foo, int Bar) { 4252 int &Baz = (Foo, Bar); 4253 // [[p]] 4254 } 4255 )"; 4256 runDataflow( 4257 Code, 4258 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4259 ASTContext &ASTCtx) { 4260 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4261 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4262 4263 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4264 ASSERT_THAT(BarDecl, NotNull()); 4265 4266 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4267 ASSERT_THAT(BazDecl, NotNull()); 4268 4269 const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl); 4270 ASSERT_THAT(BarLoc, NotNull()); 4271 4272 const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl); 4273 EXPECT_EQ(BazLoc, BarLoc); 4274 }); 4275 } 4276 4277 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) { 4278 std::string Code = R"( 4279 void target(bool Foo) { 4280 if (Foo) { 4281 (void)0; 4282 // [[if_then]] 4283 } else { 4284 (void)0; 4285 // [[if_else]] 4286 } 4287 } 4288 )"; 4289 runDataflow( 4290 Code, 4291 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4292 ASTContext &ASTCtx) { 4293 ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else")); 4294 const Environment &ThenEnv = 4295 getEnvironmentAtAnnotation(Results, "if_then"); 4296 const Environment &ElseEnv = 4297 getEnvironmentAtAnnotation(Results, "if_else"); 4298 4299 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4300 ASSERT_THAT(FooDecl, NotNull()); 4301 4302 auto &ThenFooVal= getFormula(*FooDecl, ThenEnv); 4303 EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal)); 4304 4305 auto &ElseFooVal = getFormula(*FooDecl, ElseEnv); 4306 EXPECT_TRUE( 4307 ElseEnv.flowConditionImplies(ElseEnv.arena().makeNot(ElseFooVal))); 4308 }); 4309 } 4310 4311 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) { 4312 std::string Code = R"( 4313 void target(bool Foo) { 4314 while (Foo) { 4315 (void)0; 4316 // [[loop_body]] 4317 } 4318 (void)0; 4319 // [[after_loop]] 4320 } 4321 )"; 4322 runDataflow( 4323 Code, 4324 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4325 ASTContext &ASTCtx) { 4326 ASSERT_THAT(Results.keys(), 4327 UnorderedElementsAre("loop_body", "after_loop")); 4328 const Environment &LoopBodyEnv = 4329 getEnvironmentAtAnnotation(Results, "loop_body"); 4330 const Environment &AfterLoopEnv = 4331 getEnvironmentAtAnnotation(Results, "after_loop"); 4332 4333 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4334 ASSERT_THAT(FooDecl, NotNull()); 4335 4336 auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv); 4337 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4338 4339 auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv); 4340 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4341 AfterLoopEnv.arena().makeNot(AfterLoopFooVal))); 4342 }); 4343 } 4344 4345 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) { 4346 std::string Code = R"( 4347 void target(bool Foo) { 4348 bool Bar = true; 4349 do { 4350 (void)0; 4351 // [[loop_body]] 4352 Bar = false; 4353 } while (Foo); 4354 (void)0; 4355 // [[after_loop]] 4356 } 4357 )"; 4358 runDataflow( 4359 Code, 4360 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4361 ASTContext &ASTCtx) { 4362 ASSERT_THAT(Results.keys(), 4363 UnorderedElementsAre("loop_body", "after_loop")); 4364 const Environment &LoopBodyEnv = 4365 getEnvironmentAtAnnotation(Results, "loop_body"); 4366 const Environment &AfterLoopEnv = 4367 getEnvironmentAtAnnotation(Results, "after_loop"); 4368 auto &A = AfterLoopEnv.arena(); 4369 4370 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4371 ASSERT_THAT(FooDecl, NotNull()); 4372 4373 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4374 ASSERT_THAT(BarDecl, NotNull()); 4375 4376 auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv); 4377 auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv); 4378 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies( 4379 A.makeOr(LoopBodyBarVal, LoopBodyFooVal))); 4380 4381 auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv); 4382 auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv); 4383 EXPECT_TRUE( 4384 AfterLoopEnv.flowConditionImplies(A.makeNot(AfterLoopFooVal))); 4385 EXPECT_TRUE( 4386 AfterLoopEnv.flowConditionImplies(A.makeNot(AfterLoopBarVal))); 4387 }); 4388 } 4389 4390 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) { 4391 std::string Code = R"( 4392 void target(bool Foo) { 4393 for (; Foo;) { 4394 (void)0; 4395 // [[loop_body]] 4396 } 4397 (void)0; 4398 // [[after_loop]] 4399 } 4400 )"; 4401 runDataflow( 4402 Code, 4403 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4404 ASTContext &ASTCtx) { 4405 ASSERT_THAT(Results.keys(), 4406 UnorderedElementsAre("loop_body", "after_loop")); 4407 const Environment &LoopBodyEnv = 4408 getEnvironmentAtAnnotation(Results, "loop_body"); 4409 const Environment &AfterLoopEnv = 4410 getEnvironmentAtAnnotation(Results, "after_loop"); 4411 4412 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4413 ASSERT_THAT(FooDecl, NotNull()); 4414 4415 auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv); 4416 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4417 4418 auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv); 4419 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4420 AfterLoopEnv.arena().makeNot(AfterLoopFooVal))); 4421 }); 4422 } 4423 4424 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) { 4425 std::string Code = R"( 4426 void target(bool Foo) { 4427 for (;;) { 4428 (void)0; 4429 // [[loop_body]] 4430 } 4431 } 4432 )"; 4433 runDataflow( 4434 Code, 4435 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4436 ASTContext &ASTCtx) { 4437 ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body")); 4438 const Environment &LoopBodyEnv = 4439 getEnvironmentAtAnnotation(Results, "loop_body"); 4440 4441 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4442 ASSERT_THAT(FooDecl, NotNull()); 4443 4444 auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv); 4445 EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4446 }); 4447 } 4448 4449 TEST(TransferTest, ContextSensitiveOptionDisabled) { 4450 std::string Code = R"( 4451 bool GiveBool(); 4452 void SetBool(bool &Var) { Var = true; } 4453 4454 void target() { 4455 bool Foo = GiveBool(); 4456 SetBool(Foo); 4457 // [[p]] 4458 } 4459 )"; 4460 runDataflow( 4461 Code, 4462 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4463 ASTContext &ASTCtx) { 4464 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4465 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4466 4467 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4468 ASSERT_THAT(FooDecl, NotNull()); 4469 4470 auto &FooVal = getFormula(*FooDecl, Env); 4471 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4472 EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 4473 }, 4474 {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}}); 4475 } 4476 4477 TEST(TransferTest, ContextSensitiveReturnReference) { 4478 std::string Code = R"( 4479 class S {}; 4480 S& target(bool b, S &s) { 4481 return s; 4482 // [[p]] 4483 } 4484 )"; 4485 runDataflow( 4486 Code, 4487 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4488 ASTContext &ASTCtx) { 4489 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4490 4491 const ValueDecl *SDecl = findValueDecl(ASTCtx, "s"); 4492 ASSERT_THAT(SDecl, NotNull()); 4493 4494 auto *SLoc = Env.getStorageLocation(*SDecl); 4495 ASSERT_THAT(SLoc, NotNull()); 4496 4497 ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc)); 4498 }, 4499 {BuiltinOptions{ContextSensitiveOptions{}}}); 4500 } 4501 4502 // This test is a regression test, based on a real crash. 4503 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) { 4504 std::string Code = R"( 4505 class S {}; 4506 S& target(bool b, S &s) { 4507 return b ? s : s; 4508 // [[p]] 4509 } 4510 )"; 4511 runDataflow( 4512 Code, 4513 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4514 ASTContext &ASTCtx) { 4515 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4516 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4517 4518 const ValueDecl *SDecl = findValueDecl(ASTCtx, "s"); 4519 ASSERT_THAT(SDecl, NotNull()); 4520 4521 auto *SLoc = Env.getStorageLocation(*SDecl); 4522 ASSERT_THAT(SLoc, NotNull()); 4523 EXPECT_THAT(Env.getValue(*SLoc), NotNull()); 4524 4525 auto *Loc = Env.getReturnStorageLocation(); 4526 ASSERT_THAT(Loc, NotNull()); 4527 EXPECT_THAT(Env.getValue(*Loc), NotNull()); 4528 4529 // TODO: We would really like to make this stronger assertion, but that 4530 // doesn't work because we don't propagate values correctly through 4531 // the conditional operator yet. 4532 // ASSERT_THAT(Loc, Eq(SLoc)); 4533 }, 4534 {BuiltinOptions{ContextSensitiveOptions{}}}); 4535 } 4536 4537 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) { 4538 std::string Code = R"( 4539 class S {}; 4540 S &callee(bool b, S &s1_parm, S &s2_parm) { 4541 if (b) 4542 return s1_parm; 4543 else 4544 return s2_parm; 4545 } 4546 void target(bool b) { 4547 S s1; 4548 S s2; 4549 S &return_s1 = s1; 4550 S &return_s2 = s2; 4551 S &return_dont_know = callee(b, s1, s2); 4552 // [[p]] 4553 } 4554 )"; 4555 runDataflow( 4556 Code, 4557 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4558 ASTContext &ASTCtx) { 4559 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4560 4561 const ValueDecl *S1 = findValueDecl(ASTCtx, "s1"); 4562 ASSERT_THAT(S1, NotNull()); 4563 const ValueDecl *S2 = findValueDecl(ASTCtx, "s2"); 4564 ASSERT_THAT(S2, NotNull()); 4565 const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1"); 4566 ASSERT_THAT(ReturnS1, NotNull()); 4567 const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2"); 4568 ASSERT_THAT(ReturnS2, NotNull()); 4569 const ValueDecl *ReturnDontKnow = 4570 findValueDecl(ASTCtx, "return_dont_know"); 4571 ASSERT_THAT(ReturnDontKnow, NotNull()); 4572 4573 StorageLocation *S1Loc = Env.getStorageLocation(*S1); 4574 StorageLocation *S2Loc = Env.getStorageLocation(*S2); 4575 4576 EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc)); 4577 EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc)); 4578 4579 // In the case where we don't have a consistent storage location for 4580 // the return value, the framework creates a new storage location, which 4581 // should be different from the storage locations of `s1` and `s2`. 4582 EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc)); 4583 EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc)); 4584 }, 4585 {BuiltinOptions{ContextSensitiveOptions{}}}); 4586 } 4587 4588 TEST(TransferTest, ContextSensitiveDepthZero) { 4589 std::string Code = R"( 4590 bool GiveBool(); 4591 void SetBool(bool &Var) { Var = true; } 4592 4593 void target() { 4594 bool Foo = GiveBool(); 4595 SetBool(Foo); 4596 // [[p]] 4597 } 4598 )"; 4599 runDataflow( 4600 Code, 4601 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4602 ASTContext &ASTCtx) { 4603 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4604 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4605 4606 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4607 ASSERT_THAT(FooDecl, NotNull()); 4608 4609 auto &FooVal = getFormula(*FooDecl, Env); 4610 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4611 EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 4612 }, 4613 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}}); 4614 } 4615 4616 TEST(TransferTest, ContextSensitiveSetTrue) { 4617 std::string Code = R"( 4618 bool GiveBool(); 4619 void SetBool(bool &Var) { Var = true; } 4620 4621 void target() { 4622 bool Foo = GiveBool(); 4623 SetBool(Foo); 4624 // [[p]] 4625 } 4626 )"; 4627 runDataflow( 4628 Code, 4629 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4630 ASTContext &ASTCtx) { 4631 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4632 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4633 4634 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4635 ASSERT_THAT(FooDecl, NotNull()); 4636 4637 auto &FooVal = getFormula(*FooDecl, Env); 4638 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4639 }, 4640 {BuiltinOptions{ContextSensitiveOptions{}}}); 4641 } 4642 4643 TEST(TransferTest, ContextSensitiveSetFalse) { 4644 std::string Code = R"( 4645 bool GiveBool(); 4646 void SetBool(bool &Var) { Var = false; } 4647 4648 void target() { 4649 bool Foo = GiveBool(); 4650 SetBool(Foo); 4651 // [[p]] 4652 } 4653 )"; 4654 runDataflow( 4655 Code, 4656 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4657 ASTContext &ASTCtx) { 4658 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4659 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4660 4661 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4662 ASSERT_THAT(FooDecl, NotNull()); 4663 4664 auto &FooVal = getFormula(*FooDecl, Env); 4665 EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 4666 }, 4667 {BuiltinOptions{ContextSensitiveOptions{}}}); 4668 } 4669 4670 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) { 4671 std::string Code = R"( 4672 bool GiveBool(); 4673 void SetBool(bool &Var, bool Val) { Var = Val; } 4674 4675 void target() { 4676 bool Foo = GiveBool(); 4677 bool Bar = GiveBool(); 4678 SetBool(Foo, true); 4679 SetBool(Bar, false); 4680 // [[p]] 4681 } 4682 )"; 4683 runDataflow( 4684 Code, 4685 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4686 ASTContext &ASTCtx) { 4687 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4688 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4689 auto &A = Env.arena(); 4690 4691 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4692 ASSERT_THAT(FooDecl, NotNull()); 4693 4694 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4695 ASSERT_THAT(BarDecl, NotNull()); 4696 4697 auto &FooVal = getFormula(*FooDecl, Env); 4698 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4699 EXPECT_FALSE(Env.flowConditionImplies(A.makeNot(FooVal))); 4700 4701 auto &BarVal = getFormula(*BarDecl, Env); 4702 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4703 EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(BarVal))); 4704 }, 4705 {BuiltinOptions{ContextSensitiveOptions{}}}); 4706 } 4707 4708 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) { 4709 std::string Code = R"( 4710 bool GiveBool(); 4711 void SetBool1(bool &Var) { Var = true; } 4712 void SetBool2(bool &Var) { SetBool1(Var); } 4713 4714 void target() { 4715 bool Foo = GiveBool(); 4716 SetBool2(Foo); 4717 // [[p]] 4718 } 4719 )"; 4720 runDataflow( 4721 Code, 4722 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4723 ASTContext &ASTCtx) { 4724 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4725 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4726 4727 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4728 ASSERT_THAT(FooDecl, NotNull()); 4729 4730 auto &FooVal = getFormula(*FooDecl, Env); 4731 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4732 EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 4733 }, 4734 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}}); 4735 } 4736 4737 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) { 4738 std::string Code = R"( 4739 bool GiveBool(); 4740 void SetBool1(bool &Var) { Var = true; } 4741 void SetBool2(bool &Var) { SetBool1(Var); } 4742 4743 void target() { 4744 bool Foo = GiveBool(); 4745 SetBool2(Foo); 4746 // [[p]] 4747 } 4748 )"; 4749 runDataflow( 4750 Code, 4751 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4752 ASTContext &ASTCtx) { 4753 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4754 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4755 4756 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4757 ASSERT_THAT(FooDecl, NotNull()); 4758 4759 auto &FooVal = getFormula(*FooDecl, Env); 4760 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4761 }, 4762 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}}); 4763 } 4764 4765 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) { 4766 std::string Code = R"( 4767 bool GiveBool(); 4768 void SetBool1(bool &Var) { Var = true; } 4769 void SetBool2(bool &Var) { SetBool1(Var); } 4770 void SetBool3(bool &Var) { SetBool2(Var); } 4771 4772 void target() { 4773 bool Foo = GiveBool(); 4774 SetBool3(Foo); 4775 // [[p]] 4776 } 4777 )"; 4778 runDataflow( 4779 Code, 4780 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4781 ASTContext &ASTCtx) { 4782 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4783 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4784 4785 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4786 ASSERT_THAT(FooDecl, NotNull()); 4787 4788 auto &FooVal = getFormula(*FooDecl, Env); 4789 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4790 EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 4791 }, 4792 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}}); 4793 } 4794 4795 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) { 4796 std::string Code = R"( 4797 bool GiveBool(); 4798 void SetBool1(bool &Var) { Var = true; } 4799 void SetBool2(bool &Var) { SetBool1(Var); } 4800 void SetBool3(bool &Var) { SetBool2(Var); } 4801 4802 void target() { 4803 bool Foo = GiveBool(); 4804 SetBool3(Foo); 4805 // [[p]] 4806 } 4807 )"; 4808 runDataflow( 4809 Code, 4810 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4811 ASTContext &ASTCtx) { 4812 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4813 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4814 4815 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4816 ASSERT_THAT(FooDecl, NotNull()); 4817 4818 auto &FooVal = getFormula(*FooDecl, Env); 4819 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4820 }, 4821 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}}); 4822 } 4823 4824 TEST(TransferTest, ContextSensitiveMutualRecursion) { 4825 std::string Code = R"( 4826 bool Pong(bool X, bool Y); 4827 4828 bool Ping(bool X, bool Y) { 4829 if (X) { 4830 return Y; 4831 } else { 4832 return Pong(!X, Y); 4833 } 4834 } 4835 4836 bool Pong(bool X, bool Y) { 4837 if (Y) { 4838 return X; 4839 } else { 4840 return Ping(X, !Y); 4841 } 4842 } 4843 4844 void target() { 4845 bool Foo = Ping(false, false); 4846 // [[p]] 4847 } 4848 )"; 4849 runDataflow( 4850 Code, 4851 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4852 ASTContext &ASTCtx) { 4853 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4854 // The analysis doesn't crash... 4855 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4856 4857 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4858 ASSERT_THAT(FooDecl, NotNull()); 4859 4860 auto &FooVal = getFormula(*FooDecl, Env); 4861 // ... but it also can't prove anything here. 4862 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4863 EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 4864 }, 4865 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}}); 4866 } 4867 4868 TEST(TransferTest, ContextSensitiveSetMultipleLines) { 4869 std::string Code = R"( 4870 void SetBools(bool &Var1, bool &Var2) { 4871 Var1 = true; 4872 Var2 = false; 4873 } 4874 4875 void target() { 4876 bool Foo = false; 4877 bool Bar = true; 4878 SetBools(Foo, Bar); 4879 // [[p]] 4880 } 4881 )"; 4882 runDataflow( 4883 Code, 4884 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4885 ASTContext &ASTCtx) { 4886 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4887 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4888 4889 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4890 ASSERT_THAT(FooDecl, NotNull()); 4891 4892 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4893 ASSERT_THAT(BarDecl, NotNull()); 4894 4895 auto &FooVal = getFormula(*FooDecl, Env); 4896 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4897 EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 4898 4899 auto &BarVal = getFormula(*BarDecl, Env); 4900 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4901 EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal))); 4902 }, 4903 {BuiltinOptions{ContextSensitiveOptions{}}}); 4904 } 4905 4906 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) { 4907 std::string Code = R"( 4908 void IfCond(bool Cond, bool &Then, bool &Else) { 4909 if (Cond) { 4910 Then = true; 4911 } else { 4912 Else = true; 4913 } 4914 } 4915 4916 void target() { 4917 bool Foo = false; 4918 bool Bar = false; 4919 bool Baz = false; 4920 IfCond(Foo, Bar, Baz); 4921 // [[p]] 4922 } 4923 )"; 4924 runDataflow( 4925 Code, 4926 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4927 ASTContext &ASTCtx) { 4928 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4929 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4930 4931 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4932 ASSERT_THAT(BarDecl, NotNull()); 4933 4934 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4935 ASSERT_THAT(BazDecl, NotNull()); 4936 4937 auto &BarVal = getFormula(*BarDecl, Env); 4938 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4939 EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal))); 4940 4941 auto &BazVal = getFormula(*BazDecl, Env); 4942 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 4943 EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(BazVal))); 4944 }, 4945 {BuiltinOptions{ContextSensitiveOptions{}}}); 4946 } 4947 4948 TEST(TransferTest, ContextSensitiveReturnVoid) { 4949 std::string Code = R"( 4950 void Noop() { return; } 4951 4952 void target() { 4953 Noop(); 4954 // [[p]] 4955 } 4956 )"; 4957 runDataflow( 4958 Code, 4959 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4960 ASTContext &ASTCtx) { 4961 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4962 // This just tests that the analysis doesn't crash. 4963 }, 4964 {BuiltinOptions{ContextSensitiveOptions{}}}); 4965 } 4966 4967 TEST(TransferTest, ContextSensitiveReturnTrue) { 4968 std::string Code = R"( 4969 bool GiveBool() { return true; } 4970 4971 void target() { 4972 bool Foo = GiveBool(); 4973 // [[p]] 4974 } 4975 )"; 4976 runDataflow( 4977 Code, 4978 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4979 ASTContext &ASTCtx) { 4980 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4981 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4982 4983 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4984 ASSERT_THAT(FooDecl, NotNull()); 4985 4986 auto &FooVal = getFormula(*FooDecl, Env); 4987 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4988 }, 4989 {BuiltinOptions{ContextSensitiveOptions{}}}); 4990 } 4991 4992 TEST(TransferTest, ContextSensitiveReturnFalse) { 4993 std::string Code = R"( 4994 bool GiveBool() { return false; } 4995 4996 void target() { 4997 bool Foo = GiveBool(); 4998 // [[p]] 4999 } 5000 )"; 5001 runDataflow( 5002 Code, 5003 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5004 ASTContext &ASTCtx) { 5005 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5006 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5007 5008 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5009 ASSERT_THAT(FooDecl, NotNull()); 5010 5011 auto &FooVal = getFormula(*FooDecl, Env); 5012 EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 5013 }, 5014 {BuiltinOptions{ContextSensitiveOptions{}}}); 5015 } 5016 5017 TEST(TransferTest, ContextSensitiveReturnArg) { 5018 std::string Code = R"( 5019 bool GiveBool(); 5020 bool GiveBack(bool Arg) { return Arg; } 5021 5022 void target() { 5023 bool Foo = GiveBool(); 5024 bool Bar = GiveBack(Foo); 5025 bool Baz = Foo == Bar; 5026 // [[p]] 5027 } 5028 )"; 5029 runDataflow( 5030 Code, 5031 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5032 ASTContext &ASTCtx) { 5033 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5034 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5035 5036 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 5037 ASSERT_THAT(BazDecl, NotNull()); 5038 5039 auto &BazVal = getFormula(*BazDecl, Env); 5040 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 5041 }, 5042 {BuiltinOptions{ContextSensitiveOptions{}}}); 5043 } 5044 5045 TEST(TransferTest, ContextSensitiveReturnInt) { 5046 std::string Code = R"( 5047 int identity(int x) { return x; } 5048 5049 void target() { 5050 int y = identity(42); 5051 // [[p]] 5052 } 5053 )"; 5054 runDataflow( 5055 Code, 5056 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5057 ASTContext &ASTCtx) { 5058 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5059 // This just tests that the analysis doesn't crash. 5060 }, 5061 {BuiltinOptions{ContextSensitiveOptions{}}}); 5062 } 5063 5064 TEST(TransferTest, ContextSensitiveMethodLiteral) { 5065 std::string Code = R"( 5066 class MyClass { 5067 public: 5068 bool giveBool() { return true; } 5069 }; 5070 5071 void target() { 5072 MyClass MyObj; 5073 bool Foo = MyObj.giveBool(); 5074 // [[p]] 5075 } 5076 )"; 5077 runDataflow( 5078 Code, 5079 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5080 ASTContext &ASTCtx) { 5081 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5082 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5083 5084 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5085 ASSERT_THAT(FooDecl, NotNull()); 5086 5087 auto &FooVal = getFormula(*FooDecl, Env); 5088 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5089 }, 5090 {BuiltinOptions{ContextSensitiveOptions{}}}); 5091 } 5092 5093 TEST(TransferTest, ContextSensitiveMethodGetter) { 5094 std::string Code = R"( 5095 class MyClass { 5096 public: 5097 bool getField() { return Field; } 5098 5099 bool Field; 5100 }; 5101 5102 void target() { 5103 MyClass MyObj; 5104 MyObj.Field = true; 5105 bool Foo = MyObj.getField(); 5106 // [[p]] 5107 } 5108 )"; 5109 runDataflow( 5110 Code, 5111 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5112 ASTContext &ASTCtx) { 5113 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5114 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5115 5116 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5117 ASSERT_THAT(FooDecl, NotNull()); 5118 5119 auto &FooVal = getFormula(*FooDecl, Env); 5120 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5121 }, 5122 {BuiltinOptions{ContextSensitiveOptions{}}}); 5123 } 5124 5125 TEST(TransferTest, ContextSensitiveMethodSetter) { 5126 std::string Code = R"( 5127 class MyClass { 5128 public: 5129 void setField(bool Val) { Field = Val; } 5130 5131 bool Field; 5132 }; 5133 5134 void target() { 5135 MyClass MyObj; 5136 MyObj.setField(true); 5137 bool Foo = MyObj.Field; 5138 // [[p]] 5139 } 5140 )"; 5141 runDataflow( 5142 Code, 5143 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5144 ASTContext &ASTCtx) { 5145 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5146 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5147 5148 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5149 ASSERT_THAT(FooDecl, NotNull()); 5150 5151 auto &FooVal = getFormula(*FooDecl, Env); 5152 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5153 }, 5154 {BuiltinOptions{ContextSensitiveOptions{}}}); 5155 } 5156 5157 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) { 5158 std::string Code = R"( 5159 class MyClass { 5160 public: 5161 bool getField() { return Field; } 5162 void setField(bool Val) { Field = Val; } 5163 5164 private: 5165 bool Field; 5166 }; 5167 5168 void target() { 5169 MyClass MyObj; 5170 MyObj.setField(true); 5171 bool Foo = MyObj.getField(); 5172 // [[p]] 5173 } 5174 )"; 5175 runDataflow( 5176 Code, 5177 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5178 ASTContext &ASTCtx) { 5179 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5180 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5181 5182 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5183 ASSERT_THAT(FooDecl, NotNull()); 5184 5185 auto &FooVal = getFormula(*FooDecl, Env); 5186 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5187 }, 5188 {BuiltinOptions{ContextSensitiveOptions{}}}); 5189 } 5190 5191 5192 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) { 5193 std::string Code = R"( 5194 class MyClass { 5195 public: 5196 void Inner() { MyField = true; } 5197 void Outer() { Inner(); } 5198 5199 bool MyField; 5200 }; 5201 5202 void target() { 5203 MyClass MyObj; 5204 MyObj.Outer(); 5205 bool Foo = MyObj.MyField; 5206 // [[p]] 5207 } 5208 )"; 5209 runDataflow( 5210 Code, 5211 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5212 ASTContext &ASTCtx) { 5213 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5214 ; 5215 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5216 5217 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5218 ASSERT_THAT(FooDecl, NotNull()); 5219 5220 auto &FooVal = getFormula(*FooDecl, Env); 5221 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5222 }, 5223 {BuiltinOptions{ContextSensitiveOptions{}}}); 5224 } 5225 5226 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) { 5227 std::string Code = R"( 5228 class MyClass { 5229 public: 5230 bool Inner() { return MyField; } 5231 bool Outer() { return Inner(); } 5232 5233 bool MyField; 5234 }; 5235 5236 void target() { 5237 MyClass MyObj; 5238 MyObj.MyField = true; 5239 bool Foo = MyObj.Outer(); 5240 // [[p]] 5241 } 5242 )"; 5243 runDataflow( 5244 Code, 5245 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5246 ASTContext &ASTCtx) { 5247 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5248 ; 5249 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5250 5251 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5252 ASSERT_THAT(FooDecl, NotNull()); 5253 5254 auto &FooVal = getFormula(*FooDecl, Env); 5255 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5256 }, 5257 {BuiltinOptions{ContextSensitiveOptions{}}}); 5258 } 5259 5260 TEST(TransferTest, ContextSensitiveConstructorBody) { 5261 std::string Code = R"( 5262 class MyClass { 5263 public: 5264 MyClass() { MyField = true; } 5265 5266 bool MyField; 5267 }; 5268 5269 void target() { 5270 MyClass MyObj; 5271 bool Foo = MyObj.MyField; 5272 // [[p]] 5273 } 5274 )"; 5275 runDataflow( 5276 Code, 5277 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5278 ASTContext &ASTCtx) { 5279 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5280 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5281 5282 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5283 ASSERT_THAT(FooDecl, NotNull()); 5284 5285 auto &FooVal = getFormula(*FooDecl, Env); 5286 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5287 }, 5288 {BuiltinOptions{ContextSensitiveOptions{}}}); 5289 } 5290 5291 TEST(TransferTest, ContextSensitiveConstructorInitializer) { 5292 std::string Code = R"( 5293 class MyClass { 5294 public: 5295 MyClass() : MyField(true) {} 5296 5297 bool MyField; 5298 }; 5299 5300 void target() { 5301 MyClass MyObj; 5302 bool Foo = MyObj.MyField; 5303 // [[p]] 5304 } 5305 )"; 5306 runDataflow( 5307 Code, 5308 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5309 ASTContext &ASTCtx) { 5310 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5311 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5312 5313 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5314 ASSERT_THAT(FooDecl, NotNull()); 5315 5316 auto &FooVal = getFormula(*FooDecl, Env); 5317 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5318 }, 5319 {BuiltinOptions{ContextSensitiveOptions{}}}); 5320 } 5321 5322 TEST(TransferTest, ContextSensitiveConstructorDefault) { 5323 std::string Code = R"( 5324 class MyClass { 5325 public: 5326 MyClass() = default; 5327 5328 bool MyField = true; 5329 }; 5330 5331 void target() { 5332 MyClass MyObj; 5333 bool Foo = MyObj.MyField; 5334 // [[p]] 5335 } 5336 )"; 5337 runDataflow( 5338 Code, 5339 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5340 ASTContext &ASTCtx) { 5341 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5342 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5343 5344 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5345 ASSERT_THAT(FooDecl, NotNull()); 5346 5347 auto &FooVal = getFormula(*FooDecl, Env); 5348 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5349 }, 5350 {BuiltinOptions{ContextSensitiveOptions{}}}); 5351 } 5352 5353 TEST(TransferTest, UnnamedBitfieldInitializer) { 5354 std::string Code = R"( 5355 struct B {}; 5356 struct A { 5357 unsigned a; 5358 unsigned : 4; 5359 unsigned c; 5360 B b; 5361 }; 5362 void target() { 5363 A a = {}; 5364 A test = a; 5365 (void)test.c; 5366 } 5367 )"; 5368 runDataflow( 5369 Code, 5370 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5371 ASTContext &ASTCtx) { 5372 // This doesn't need a body because this test was crashing the framework 5373 // before handling correctly Unnamed bitfields in `InitListExpr`. 5374 }); 5375 } 5376 5377 // Repro for a crash that used to occur with chained short-circuiting logical 5378 // operators. 5379 TEST(TransferTest, ChainedLogicalOps) { 5380 std::string Code = R"( 5381 bool target() { 5382 bool b = true || false || false || false; 5383 // [[p]] 5384 return b; 5385 } 5386 )"; 5387 runDataflow( 5388 Code, 5389 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5390 ASTContext &ASTCtx) { 5391 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5392 auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula(); 5393 EXPECT_TRUE(Env.flowConditionImplies(B)); 5394 }); 5395 } 5396 5397 // Repro for a crash that used to occur when we call a `noreturn` function 5398 // within one of the operands of a `&&` or `||` operator. 5399 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) { 5400 std::string Code = R"( 5401 __attribute__((noreturn)) int doesnt_return(); 5402 bool some_condition(); 5403 void target(bool b1, bool b2) { 5404 // Neither of these should crash. In addition, if we don't terminate the 5405 // program, we know that the operators need to trigger the short-circuit 5406 // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr` 5407 // will be true. 5408 bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0; 5409 bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0; 5410 5411 // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the 5412 // entire expression unreachable. So we know that in both of the following 5413 // cases, if `target()` terminates, the `else` branch was taken. 5414 bool NoreturnOnLhsMakesAndUnreachable = false; 5415 if (some_condition()) 5416 doesnt_return() > 0 && some_condition(); 5417 else 5418 NoreturnOnLhsMakesAndUnreachable = true; 5419 5420 bool NoreturnOnLhsMakesOrUnreachable = false; 5421 if (some_condition()) 5422 doesnt_return() > 0 || some_condition(); 5423 else 5424 NoreturnOnLhsMakesOrUnreachable = true; 5425 5426 // [[p]] 5427 } 5428 )"; 5429 runDataflow( 5430 Code, 5431 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5432 ASTContext &ASTCtx) { 5433 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5434 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5435 auto &A = Env.arena(); 5436 5437 // Check that [[p]] is reachable with a non-false flow condition. 5438 EXPECT_FALSE(Env.flowConditionImplies(A.makeLiteral(false))); 5439 5440 auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula(); 5441 EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(B1))); 5442 5443 auto &NoreturnOnRhsOfAnd = 5444 getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula(); 5445 EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(NoreturnOnRhsOfAnd))); 5446 5447 auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula(); 5448 EXPECT_TRUE(Env.flowConditionImplies(B2)); 5449 5450 auto &NoreturnOnRhsOfOr = 5451 getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr") 5452 .formula(); 5453 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnRhsOfOr)); 5454 5455 auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>( 5456 ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula(); 5457 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesAndUnreachable)); 5458 5459 auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>( 5460 ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula(); 5461 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesOrUnreachable)); 5462 }); 5463 } 5464 5465 TEST(TransferTest, NewExpressions) { 5466 std::string Code = R"( 5467 void target() { 5468 int *p = new int(42); 5469 // [[after_new]] 5470 } 5471 )"; 5472 runDataflow( 5473 Code, 5474 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5475 ASTContext &ASTCtx) { 5476 const Environment &Env = 5477 getEnvironmentAtAnnotation(Results, "after_new"); 5478 5479 auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p"); 5480 5481 EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull()); 5482 }); 5483 } 5484 5485 TEST(TransferTest, NewExpressions_Structs) { 5486 std::string Code = R"( 5487 struct Inner { 5488 int InnerField; 5489 }; 5490 5491 struct Outer { 5492 Inner OuterField; 5493 }; 5494 5495 void target() { 5496 Outer *p = new Outer; 5497 // Access the fields to make sure the analysis actually generates children 5498 // for them in the `RecordStorageLocation` and `RecordValue`. 5499 p->OuterField.InnerField; 5500 // [[after_new]] 5501 } 5502 )"; 5503 runDataflow( 5504 Code, 5505 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5506 ASTContext &ASTCtx) { 5507 const Environment &Env = 5508 getEnvironmentAtAnnotation(Results, "after_new"); 5509 5510 const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField"); 5511 const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField"); 5512 5513 auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p"); 5514 5515 auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc()); 5516 auto &OuterFieldLoc = 5517 *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField)); 5518 auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField); 5519 5520 // Values for the struct and all fields exist after the new. 5521 EXPECT_THAT(Env.getValue(OuterLoc), NotNull()); 5522 EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull()); 5523 EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull()); 5524 }); 5525 } 5526 5527 TEST(TransferTest, FunctionToPointerDecayHasValue) { 5528 std::string Code = R"( 5529 struct A { static void static_member_func(); }; 5530 void target() { 5531 // To check that we're treating function-to-pointer decay correctly, 5532 // create two pointers, then verify they refer to the same storage 5533 // location. 5534 // We need to do the test this way because even if an initializer (in this 5535 // case, the function-to-pointer decay) does not create a value, we still 5536 // create a value for the variable. 5537 void (*non_member_p1)() = target; 5538 void (*non_member_p2)() = target; 5539 5540 // Do the same thing but for a static member function. 5541 void (*member_p1)() = A::static_member_func; 5542 void (*member_p2)() = A::static_member_func; 5543 // [[p]] 5544 } 5545 )"; 5546 runDataflow( 5547 Code, 5548 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5549 ASTContext &ASTCtx) { 5550 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5551 5552 auto &NonMemberP1 = 5553 getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1"); 5554 auto &NonMemberP2 = 5555 getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2"); 5556 EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc()); 5557 5558 auto &MemberP1 = 5559 getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1"); 5560 auto &MemberP2 = 5561 getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2"); 5562 EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc()); 5563 }); 5564 } 5565 5566 // Check that a builtin function is not associated with a value. (It's only 5567 // possible to call builtin functions directly, not take their address.) 5568 TEST(TransferTest, BuiltinFunctionModeled) { 5569 std::string Code = R"( 5570 void target() { 5571 __builtin_expect(0, 0); 5572 // [[p]] 5573 } 5574 )"; 5575 runDataflow( 5576 Code, 5577 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5578 ASTContext &ASTCtx) { 5579 using ast_matchers::selectFirst; 5580 using ast_matchers::match; 5581 using ast_matchers::traverse; 5582 using ast_matchers::implicitCastExpr; 5583 using ast_matchers::hasCastKind; 5584 5585 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5586 5587 auto *ImplicitCast = selectFirst<ImplicitCastExpr>( 5588 "implicit_cast", 5589 match(traverse(TK_AsIs, 5590 implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr)) 5591 .bind("implicit_cast")), 5592 ASTCtx)); 5593 5594 ASSERT_THAT(ImplicitCast, NotNull()); 5595 EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull()); 5596 }); 5597 } 5598 5599 // Check that a callee of a member operator call is modeled as a `PointerValue`. 5600 // Member operator calls are unusual in that their callee is a pointer that 5601 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static 5602 // member functions, the callee is a `MemberExpr` (which does not have pointer 5603 // type). 5604 // We want to make sure that we produce a pointer value for the callee in this 5605 // specific scenario and that its storage location is durable (for convergence). 5606 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) { 5607 std::string Code = R"( 5608 struct S { 5609 bool operator!=(S s); 5610 }; 5611 void target() { 5612 S s; 5613 (void)(s != s); 5614 (void)(s != s); 5615 // [[p]] 5616 } 5617 )"; 5618 runDataflow( 5619 Code, 5620 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5621 ASTContext &ASTCtx) { 5622 using ast_matchers::selectFirst; 5623 using ast_matchers::match; 5624 using ast_matchers::traverse; 5625 using ast_matchers::cxxOperatorCallExpr; 5626 5627 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5628 5629 auto Matches = match( 5630 traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx); 5631 5632 ASSERT_EQ(Matches.size(), 2UL); 5633 5634 auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call"); 5635 auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call"); 5636 5637 ASSERT_THAT(Call1, NotNull()); 5638 ASSERT_THAT(Call2, NotNull()); 5639 5640 EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(), 5641 CK_FunctionToPointerDecay); 5642 EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(), 5643 CK_FunctionToPointerDecay); 5644 5645 auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee())); 5646 auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee())); 5647 5648 ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc()); 5649 }); 5650 } 5651 5652 // Check that fields of anonymous records are modeled. 5653 TEST(TransferTest, AnonymousStruct) { 5654 std::string Code = R"( 5655 struct S { 5656 struct { 5657 bool b; 5658 }; 5659 }; 5660 void target() { 5661 S s; 5662 s.b = true; 5663 // [[p]] 5664 } 5665 )"; 5666 runDataflow( 5667 Code, 5668 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5669 ASTContext &ASTCtx) { 5670 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5671 const ValueDecl *SDecl = findValueDecl(ASTCtx, "s"); 5672 const ValueDecl *BDecl = findValueDecl(ASTCtx, "b"); 5673 const IndirectFieldDecl *IndirectField = 5674 findIndirectFieldDecl(ASTCtx, "b"); 5675 5676 auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl)); 5677 auto &AnonStruct = *cast<RecordStorageLocation>( 5678 S->getChild(*cast<ValueDecl>(IndirectField->chain().front()))); 5679 5680 auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env)); 5681 ASSERT_TRUE(Env.flowConditionImplies(B->formula())); 5682 }); 5683 } 5684 5685 TEST(TransferTest, AnonymousStructWithInitializer) { 5686 std::string Code = R"( 5687 struct target { 5688 target() { 5689 (void)0; 5690 // [[p]] 5691 } 5692 struct { 5693 bool b = true; 5694 }; 5695 }; 5696 )"; 5697 runDataflow( 5698 Code, 5699 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5700 ASTContext &ASTCtx) { 5701 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5702 const ValueDecl *BDecl = findValueDecl(ASTCtx, "b"); 5703 const IndirectFieldDecl *IndirectField = 5704 findIndirectFieldDecl(ASTCtx, "b"); 5705 5706 auto *ThisLoc = 5707 cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation()); 5708 auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild( 5709 *cast<ValueDecl>(IndirectField->chain().front()))); 5710 5711 auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env)); 5712 ASSERT_TRUE(Env.flowConditionImplies(B->formula())); 5713 }); 5714 } 5715 5716 TEST(TransferTest, AnonymousStructWithReferenceField) { 5717 std::string Code = R"( 5718 int global_i = 0; 5719 struct target { 5720 target() { 5721 (void)0; 5722 // [[p]] 5723 } 5724 struct { 5725 int &i = global_i; 5726 }; 5727 }; 5728 )"; 5729 runDataflow( 5730 Code, 5731 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5732 ASTContext &ASTCtx) { 5733 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5734 const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i"); 5735 const ValueDecl *IDecl = findValueDecl(ASTCtx, "i"); 5736 const IndirectFieldDecl *IndirectField = 5737 findIndirectFieldDecl(ASTCtx, "i"); 5738 5739 auto *ThisLoc = 5740 cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation()); 5741 auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild( 5742 *cast<ValueDecl>(IndirectField->chain().front()))); 5743 5744 ASSERT_EQ(AnonStruct.getChild(*IDecl), 5745 Env.getStorageLocation(*GlobalIDecl)); 5746 }); 5747 } 5748 5749 } // namespace 5750