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 "NoopAnalysis.h" 10 #include "TestingSupport.h" 11 #include "clang/AST/ASTContext.h" 12 #include "clang/AST/Decl.h" 13 #include "clang/ASTMatchers/ASTMatchFinder.h" 14 #include "clang/ASTMatchers/ASTMatchers.h" 15 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.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/StringRef.h" 21 #include "llvm/Support/Casting.h" 22 #include "llvm/Testing/Support/Error.h" 23 #include "gmock/gmock.h" 24 #include "gtest/gtest.h" 25 #include <string> 26 #include <utility> 27 28 namespace { 29 30 using namespace clang; 31 using namespace dataflow; 32 using namespace test; 33 using ::testing::_; 34 using ::testing::ElementsAre; 35 using ::testing::IsNull; 36 using ::testing::NotNull; 37 using ::testing::Pair; 38 using ::testing::SizeIs; 39 40 template <typename Matcher> 41 void runDataflow(llvm::StringRef Code, Matcher Match, 42 LangStandard::Kind Std = LangStandard::lang_cxx17, 43 bool ApplyBuiltinTransfer = true, 44 llvm::StringRef TargetFun = "target") { 45 ASSERT_THAT_ERROR( 46 test::checkDataflow<NoopAnalysis>( 47 Code, TargetFun, 48 [ApplyBuiltinTransfer](ASTContext &C, Environment &) { 49 return NoopAnalysis(C, ApplyBuiltinTransfer); 50 }, 51 [&Match]( 52 llvm::ArrayRef< 53 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 54 Results, 55 ASTContext &ASTCtx) { Match(Results, ASTCtx); }, 56 {"-fsyntax-only", "-fno-delayed-template-parsing", 57 "-std=" + 58 std::string( 59 LangStandard::getLangStandardForKind(Std).getName())}), 60 llvm::Succeeded()); 61 } 62 63 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) { 64 std::string Code = R"( 65 void target() { 66 int Foo; 67 // [[p]] 68 } 69 )"; 70 runDataflow( 71 Code, 72 [](llvm::ArrayRef< 73 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 74 Results, 75 ASTContext &ASTCtx) { 76 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 77 const Environment &Env = Results[0].second.Env; 78 79 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 80 ASSERT_THAT(FooDecl, NotNull()); 81 82 EXPECT_EQ(Env.getStorageLocation(*FooDecl, SkipPast::None), nullptr); 83 }, 84 LangStandard::lang_cxx17, 85 /*ApplyBuiltinTransfer=*/false); 86 } 87 88 TEST(TransferTest, BoolVarDecl) { 89 std::string Code = R"( 90 void target() { 91 bool Foo; 92 // [[p]] 93 } 94 )"; 95 runDataflow(Code, 96 [](llvm::ArrayRef< 97 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 98 Results, 99 ASTContext &ASTCtx) { 100 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 101 const Environment &Env = Results[0].second.Env; 102 103 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 104 ASSERT_THAT(FooDecl, NotNull()); 105 106 const StorageLocation *FooLoc = 107 Env.getStorageLocation(*FooDecl, SkipPast::None); 108 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 109 110 const Value *FooVal = Env.getValue(*FooLoc); 111 EXPECT_TRUE(isa_and_nonnull<BoolValue>(FooVal)); 112 }); 113 } 114 115 TEST(TransferTest, IntVarDecl) { 116 std::string Code = R"( 117 void target() { 118 int Foo; 119 // [[p]] 120 } 121 )"; 122 runDataflow(Code, 123 [](llvm::ArrayRef< 124 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 125 Results, 126 ASTContext &ASTCtx) { 127 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 128 const Environment &Env = Results[0].second.Env; 129 130 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 131 ASSERT_THAT(FooDecl, NotNull()); 132 133 const StorageLocation *FooLoc = 134 Env.getStorageLocation(*FooDecl, SkipPast::None); 135 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 136 137 const Value *FooVal = Env.getValue(*FooLoc); 138 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 139 }); 140 } 141 142 TEST(TransferTest, StructVarDecl) { 143 std::string Code = R"( 144 struct A { 145 int Bar; 146 }; 147 148 void target() { 149 A Foo; 150 // [[p]] 151 } 152 )"; 153 runDataflow( 154 Code, [](llvm::ArrayRef< 155 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 156 Results, 157 ASTContext &ASTCtx) { 158 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 159 const Environment &Env = Results[0].second.Env; 160 161 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 162 ASSERT_THAT(FooDecl, NotNull()); 163 164 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 165 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 166 167 FieldDecl *BarDecl = nullptr; 168 for (FieldDecl *Field : FooFields) { 169 if (Field->getNameAsString() == "Bar") { 170 BarDecl = Field; 171 } else { 172 FAIL() << "Unexpected field: " << Field->getNameAsString(); 173 } 174 } 175 ASSERT_THAT(BarDecl, NotNull()); 176 177 const auto *FooLoc = cast<AggregateStorageLocation>( 178 Env.getStorageLocation(*FooDecl, SkipPast::None)); 179 const auto *BarLoc = 180 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 181 182 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 183 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 184 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 185 }); 186 } 187 188 TEST(TransferTest, StructVarDeclWithInit) { 189 std::string Code = R"( 190 struct A { 191 int Bar; 192 }; 193 194 A Gen(); 195 196 void target() { 197 A Foo = Gen(); 198 // [[p]] 199 } 200 )"; 201 runDataflow( 202 Code, [](llvm::ArrayRef< 203 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 204 Results, 205 ASTContext &ASTCtx) { 206 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 207 const Environment &Env = Results[0].second.Env; 208 209 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 210 ASSERT_THAT(FooDecl, NotNull()); 211 212 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 213 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 214 215 FieldDecl *BarDecl = nullptr; 216 for (FieldDecl *Field : FooFields) { 217 if (Field->getNameAsString() == "Bar") { 218 BarDecl = Field; 219 } else { 220 FAIL() << "Unexpected field: " << Field->getNameAsString(); 221 } 222 } 223 ASSERT_THAT(BarDecl, NotNull()); 224 225 const auto *FooLoc = cast<AggregateStorageLocation>( 226 Env.getStorageLocation(*FooDecl, SkipPast::None)); 227 const auto *BarLoc = 228 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 229 230 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 231 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 232 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 233 }); 234 } 235 236 TEST(TransferTest, ClassVarDecl) { 237 std::string Code = R"( 238 class A { 239 int Bar; 240 }; 241 242 void target() { 243 A Foo; 244 // [[p]] 245 } 246 )"; 247 runDataflow( 248 Code, [](llvm::ArrayRef< 249 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 250 Results, 251 ASTContext &ASTCtx) { 252 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 253 const Environment &Env = Results[0].second.Env; 254 255 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 256 ASSERT_THAT(FooDecl, NotNull()); 257 258 ASSERT_TRUE(FooDecl->getType()->isClassType()); 259 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 260 261 FieldDecl *BarDecl = nullptr; 262 for (FieldDecl *Field : FooFields) { 263 if (Field->getNameAsString() == "Bar") { 264 BarDecl = Field; 265 } else { 266 FAIL() << "Unexpected field: " << Field->getNameAsString(); 267 } 268 } 269 ASSERT_THAT(BarDecl, NotNull()); 270 271 const auto *FooLoc = cast<AggregateStorageLocation>( 272 Env.getStorageLocation(*FooDecl, SkipPast::None)); 273 const auto *BarLoc = 274 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 275 276 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 277 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 278 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 279 }); 280 } 281 282 TEST(TransferTest, ReferenceVarDecl) { 283 std::string Code = R"( 284 struct A {}; 285 286 A &getA(); 287 288 void target() { 289 A &Foo = getA(); 290 // [[p]] 291 } 292 )"; 293 runDataflow( 294 Code, [](llvm::ArrayRef< 295 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 296 Results, 297 ASTContext &ASTCtx) { 298 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 299 const Environment &Env = Results[0].second.Env; 300 301 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 302 ASSERT_THAT(FooDecl, NotNull()); 303 304 const StorageLocation *FooLoc = 305 Env.getStorageLocation(*FooDecl, SkipPast::None); 306 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 307 308 const ReferenceValue *FooVal = 309 cast<ReferenceValue>(Env.getValue(*FooLoc)); 310 const StorageLocation &FooReferentLoc = FooVal->getReferentLoc(); 311 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooReferentLoc)); 312 313 const Value *FooReferentVal = Env.getValue(FooReferentLoc); 314 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal)); 315 }); 316 } 317 318 TEST(TransferTest, SelfReferentialReferenceVarDecl) { 319 std::string Code = R"( 320 struct A; 321 322 struct B {}; 323 324 struct C { 325 A &FooRef; 326 A *FooPtr; 327 B &BazRef; 328 B *BazPtr; 329 }; 330 331 struct A { 332 C &Bar; 333 }; 334 335 A &getA(); 336 337 void target() { 338 A &Foo = getA(); 339 // [[p]] 340 } 341 )"; 342 runDataflow(Code, [](llvm::ArrayRef<std::pair< 343 std::string, DataflowAnalysisState<NoopLattice>>> 344 Results, 345 ASTContext &ASTCtx) { 346 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 347 const Environment &Env = Results[0].second.Env; 348 349 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 350 ASSERT_THAT(FooDecl, NotNull()); 351 352 ASSERT_TRUE(FooDecl->getType()->isReferenceType()); 353 ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType()); 354 const auto FooFields = 355 FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields(); 356 357 FieldDecl *BarDecl = nullptr; 358 for (FieldDecl *Field : FooFields) { 359 if (Field->getNameAsString() == "Bar") { 360 BarDecl = Field; 361 } else { 362 FAIL() << "Unexpected field: " << Field->getNameAsString(); 363 } 364 } 365 ASSERT_THAT(BarDecl, NotNull()); 366 367 ASSERT_TRUE(BarDecl->getType()->isReferenceType()); 368 ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType()); 369 const auto BarFields = 370 BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields(); 371 372 FieldDecl *FooRefDecl = nullptr; 373 FieldDecl *FooPtrDecl = nullptr; 374 FieldDecl *BazRefDecl = nullptr; 375 FieldDecl *BazPtrDecl = nullptr; 376 for (FieldDecl *Field : BarFields) { 377 if (Field->getNameAsString() == "FooRef") { 378 FooRefDecl = Field; 379 } else if (Field->getNameAsString() == "FooPtr") { 380 FooPtrDecl = Field; 381 } else if (Field->getNameAsString() == "BazRef") { 382 BazRefDecl = Field; 383 } else if (Field->getNameAsString() == "BazPtr") { 384 BazPtrDecl = Field; 385 } else { 386 FAIL() << "Unexpected field: " << Field->getNameAsString(); 387 } 388 } 389 ASSERT_THAT(FooRefDecl, NotNull()); 390 ASSERT_THAT(FooPtrDecl, NotNull()); 391 ASSERT_THAT(BazRefDecl, NotNull()); 392 ASSERT_THAT(BazPtrDecl, NotNull()); 393 394 const auto *FooLoc = cast<ScalarStorageLocation>( 395 Env.getStorageLocation(*FooDecl, SkipPast::None)); 396 const auto *FooVal = cast<ReferenceValue>(Env.getValue(*FooLoc)); 397 const auto *FooReferentVal = 398 cast<StructValue>(Env.getValue(FooVal->getReferentLoc())); 399 400 const auto *BarVal = 401 cast<ReferenceValue>(FooReferentVal->getChild(*BarDecl)); 402 const auto *BarReferentVal = 403 cast<StructValue>(Env.getValue(BarVal->getReferentLoc())); 404 405 const auto *FooRefVal = 406 cast<ReferenceValue>(BarReferentVal->getChild(*FooRefDecl)); 407 const StorageLocation &FooReferentLoc = FooRefVal->getReferentLoc(); 408 EXPECT_THAT(Env.getValue(FooReferentLoc), IsNull()); 409 410 const auto *FooPtrVal = 411 cast<PointerValue>(BarReferentVal->getChild(*FooPtrDecl)); 412 const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc(); 413 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull()); 414 415 const auto *BazRefVal = 416 cast<ReferenceValue>(BarReferentVal->getChild(*BazRefDecl)); 417 const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc(); 418 EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull()); 419 420 const auto *BazPtrVal = 421 cast<PointerValue>(BarReferentVal->getChild(*BazPtrDecl)); 422 const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc(); 423 EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); 424 }); 425 } 426 427 TEST(TransferTest, PointerVarDecl) { 428 std::string Code = R"( 429 struct A {}; 430 431 A *getA(); 432 433 void target() { 434 A *Foo = getA(); 435 // [[p]] 436 } 437 )"; 438 runDataflow( 439 Code, [](llvm::ArrayRef< 440 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 441 Results, 442 ASTContext &ASTCtx) { 443 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 444 const Environment &Env = Results[0].second.Env; 445 446 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 447 ASSERT_THAT(FooDecl, NotNull()); 448 449 const StorageLocation *FooLoc = 450 Env.getStorageLocation(*FooDecl, SkipPast::None); 451 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 452 453 const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 454 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 455 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 456 457 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 458 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 459 }); 460 } 461 462 TEST(TransferTest, SelfReferentialPointerVarDecl) { 463 std::string Code = R"( 464 struct A; 465 466 struct B {}; 467 468 struct C { 469 A &FooRef; 470 A *FooPtr; 471 B &BazRef; 472 B *BazPtr; 473 }; 474 475 struct A { 476 C *Bar; 477 }; 478 479 A *getA(); 480 481 void target() { 482 A *Foo = getA(); 483 // [[p]] 484 } 485 )"; 486 runDataflow( 487 Code, [](llvm::ArrayRef< 488 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 489 Results, 490 ASTContext &ASTCtx) { 491 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 492 const Environment &Env = Results[0].second.Env; 493 494 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 495 ASSERT_THAT(FooDecl, NotNull()); 496 497 ASSERT_TRUE(FooDecl->getType()->isPointerType()); 498 ASSERT_TRUE(FooDecl->getType() 499 ->getAs<PointerType>() 500 ->getPointeeType() 501 ->isStructureType()); 502 const auto FooFields = FooDecl->getType() 503 ->getAs<PointerType>() 504 ->getPointeeType() 505 ->getAsRecordDecl() 506 ->fields(); 507 508 FieldDecl *BarDecl = nullptr; 509 for (FieldDecl *Field : FooFields) { 510 if (Field->getNameAsString() == "Bar") { 511 BarDecl = Field; 512 } else { 513 FAIL() << "Unexpected field: " << Field->getNameAsString(); 514 } 515 } 516 ASSERT_THAT(BarDecl, NotNull()); 517 518 ASSERT_TRUE(BarDecl->getType()->isPointerType()); 519 ASSERT_TRUE(BarDecl->getType() 520 ->getAs<PointerType>() 521 ->getPointeeType() 522 ->isStructureType()); 523 const auto BarFields = BarDecl->getType() 524 ->getAs<PointerType>() 525 ->getPointeeType() 526 ->getAsRecordDecl() 527 ->fields(); 528 529 FieldDecl *FooRefDecl = nullptr; 530 FieldDecl *FooPtrDecl = nullptr; 531 FieldDecl *BazRefDecl = nullptr; 532 FieldDecl *BazPtrDecl = nullptr; 533 for (FieldDecl *Field : BarFields) { 534 if (Field->getNameAsString() == "FooRef") { 535 FooRefDecl = Field; 536 } else if (Field->getNameAsString() == "FooPtr") { 537 FooPtrDecl = Field; 538 } else if (Field->getNameAsString() == "BazRef") { 539 BazRefDecl = Field; 540 } else if (Field->getNameAsString() == "BazPtr") { 541 BazPtrDecl = Field; 542 } else { 543 FAIL() << "Unexpected field: " << Field->getNameAsString(); 544 } 545 } 546 ASSERT_THAT(FooRefDecl, NotNull()); 547 ASSERT_THAT(FooPtrDecl, NotNull()); 548 ASSERT_THAT(BazRefDecl, NotNull()); 549 ASSERT_THAT(BazPtrDecl, NotNull()); 550 551 const auto *FooLoc = cast<ScalarStorageLocation>( 552 Env.getStorageLocation(*FooDecl, SkipPast::None)); 553 const auto *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 554 const auto *FooPointeeVal = 555 cast<StructValue>(Env.getValue(FooVal->getPointeeLoc())); 556 557 const auto *BarVal = 558 cast<PointerValue>(FooPointeeVal->getChild(*BarDecl)); 559 const auto *BarPointeeVal = 560 cast<StructValue>(Env.getValue(BarVal->getPointeeLoc())); 561 562 const auto *FooRefVal = 563 cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl)); 564 const StorageLocation &FooReferentLoc = FooRefVal->getReferentLoc(); 565 EXPECT_THAT(Env.getValue(FooReferentLoc), IsNull()); 566 567 const auto *FooPtrVal = 568 cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl)); 569 const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc(); 570 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull()); 571 572 const auto *BazRefVal = 573 cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl)); 574 const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc(); 575 EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull()); 576 577 const auto *BazPtrVal = 578 cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl)); 579 const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc(); 580 EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); 581 }); 582 } 583 584 TEST(TransferTest, MultipleVarsDecl) { 585 std::string Code = R"( 586 void target() { 587 int Foo, Bar; 588 (void)0; 589 // [[p]] 590 } 591 )"; 592 runDataflow(Code, 593 [](llvm::ArrayRef< 594 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 595 Results, 596 ASTContext &ASTCtx) { 597 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 598 const Environment &Env = Results[0].second.Env; 599 600 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 601 ASSERT_THAT(FooDecl, NotNull()); 602 603 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 604 ASSERT_THAT(BarDecl, NotNull()); 605 606 const StorageLocation *FooLoc = 607 Env.getStorageLocation(*FooDecl, SkipPast::None); 608 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 609 610 const StorageLocation *BarLoc = 611 Env.getStorageLocation(*BarDecl, SkipPast::None); 612 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 613 614 const Value *FooVal = Env.getValue(*FooLoc); 615 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 616 617 const Value *BarVal = Env.getValue(*BarLoc); 618 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 619 }); 620 } 621 622 TEST(TransferTest, JoinVarDecl) { 623 std::string Code = R"( 624 void target(bool B) { 625 int Foo; 626 // [[p1]] 627 if (B) { 628 int Bar; 629 // [[p2]] 630 } else { 631 int Baz; 632 // [[p3]] 633 } 634 (void)0; 635 // [[p4]] 636 } 637 )"; 638 runDataflow(Code, [](llvm::ArrayRef<std::pair< 639 std::string, DataflowAnalysisState<NoopLattice>>> 640 Results, 641 ASTContext &ASTCtx) { 642 ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _), 643 Pair("p2", _), Pair("p1", _))); 644 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 645 ASSERT_THAT(FooDecl, NotNull()); 646 647 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 648 ASSERT_THAT(BarDecl, NotNull()); 649 650 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 651 ASSERT_THAT(BazDecl, NotNull()); 652 653 const Environment &Env1 = Results[3].second.Env; 654 const StorageLocation *FooLoc = 655 Env1.getStorageLocation(*FooDecl, SkipPast::None); 656 EXPECT_THAT(FooLoc, NotNull()); 657 EXPECT_THAT(Env1.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 658 EXPECT_THAT(Env1.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 659 660 const Environment &Env2 = Results[2].second.Env; 661 EXPECT_EQ(Env2.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 662 EXPECT_THAT(Env2.getStorageLocation(*BarDecl, SkipPast::None), NotNull()); 663 EXPECT_THAT(Env2.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 664 665 const Environment &Env3 = Results[1].second.Env; 666 EXPECT_EQ(Env3.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 667 EXPECT_THAT(Env3.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 668 EXPECT_THAT(Env3.getStorageLocation(*BazDecl, SkipPast::None), NotNull()); 669 670 const Environment &Env4 = Results[0].second.Env; 671 EXPECT_EQ(Env4.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 672 EXPECT_THAT(Env4.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 673 EXPECT_THAT(Env4.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 674 }); 675 } 676 677 TEST(TransferTest, BinaryOperatorAssign) { 678 std::string Code = R"( 679 void target() { 680 int Foo; 681 int Bar; 682 (Bar) = (Foo); 683 // [[p]] 684 } 685 )"; 686 runDataflow(Code, 687 [](llvm::ArrayRef< 688 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 689 Results, 690 ASTContext &ASTCtx) { 691 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 692 const Environment &Env = Results[0].second.Env; 693 694 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 695 ASSERT_THAT(FooDecl, NotNull()); 696 697 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 698 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 699 700 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 701 ASSERT_THAT(BarDecl, NotNull()); 702 703 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 704 }); 705 } 706 707 TEST(TransferTest, VarDeclInitAssign) { 708 std::string Code = R"( 709 void target() { 710 int Foo; 711 int Bar = Foo; 712 // [[p]] 713 } 714 )"; 715 runDataflow(Code, 716 [](llvm::ArrayRef< 717 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 718 Results, 719 ASTContext &ASTCtx) { 720 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 721 const Environment &Env = Results[0].second.Env; 722 723 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 724 ASSERT_THAT(FooDecl, NotNull()); 725 726 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 727 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 728 729 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 730 ASSERT_THAT(BarDecl, NotNull()); 731 732 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 733 }); 734 } 735 736 TEST(TransferTest, VarDeclInitAssignChained) { 737 std::string Code = R"( 738 void target() { 739 int Foo; 740 int Bar; 741 int Baz = (Bar = Foo); 742 // [[p]] 743 } 744 )"; 745 runDataflow(Code, 746 [](llvm::ArrayRef< 747 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 748 Results, 749 ASTContext &ASTCtx) { 750 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 751 const Environment &Env = Results[0].second.Env; 752 753 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 754 ASSERT_THAT(FooDecl, NotNull()); 755 756 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 757 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 758 759 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 760 ASSERT_THAT(BarDecl, NotNull()); 761 762 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 763 ASSERT_THAT(BazDecl, NotNull()); 764 765 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 766 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal); 767 }); 768 } 769 770 TEST(TransferTest, VarDeclInitAssignPtrDeref) { 771 std::string Code = R"( 772 void target() { 773 int Foo; 774 int *Bar; 775 *(Bar) = Foo; 776 int Baz = *(Bar); 777 // [[p]] 778 } 779 )"; 780 runDataflow(Code, 781 [](llvm::ArrayRef< 782 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 783 Results, 784 ASTContext &ASTCtx) { 785 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 786 const Environment &Env = Results[0].second.Env; 787 788 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 789 ASSERT_THAT(FooDecl, NotNull()); 790 791 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 792 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 793 794 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 795 ASSERT_THAT(BarDecl, NotNull()); 796 797 const auto *BarVal = 798 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 799 EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal); 800 801 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 802 ASSERT_THAT(BazDecl, NotNull()); 803 804 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal); 805 }); 806 } 807 808 TEST(TransferTest, AssignToAndFromReference) { 809 std::string Code = R"( 810 void target() { 811 int Foo; 812 int Bar; 813 int &Baz = Foo; 814 // [[p1]] 815 Baz = Bar; 816 int Qux = Baz; 817 int &Quux = Baz; 818 // [[p2]] 819 } 820 )"; 821 runDataflow( 822 Code, [](llvm::ArrayRef< 823 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 824 Results, 825 ASTContext &ASTCtx) { 826 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 827 const Environment &Env1 = Results[0].second.Env; 828 const Environment &Env2 = Results[1].second.Env; 829 830 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 831 ASSERT_THAT(FooDecl, NotNull()); 832 833 const Value *FooVal = Env1.getValue(*FooDecl, SkipPast::None); 834 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 835 836 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 837 ASSERT_THAT(BarDecl, NotNull()); 838 839 const Value *BarVal = Env1.getValue(*BarDecl, SkipPast::None); 840 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 841 842 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 843 ASSERT_THAT(BazDecl, NotNull()); 844 845 EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), FooVal); 846 847 EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BarVal); 848 EXPECT_EQ(Env2.getValue(*FooDecl, SkipPast::None), BarVal); 849 850 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 851 ASSERT_THAT(QuxDecl, NotNull()); 852 EXPECT_EQ(Env2.getValue(*QuxDecl, SkipPast::None), BarVal); 853 854 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 855 ASSERT_THAT(QuuxDecl, NotNull()); 856 EXPECT_EQ(Env2.getValue(*QuuxDecl, SkipPast::Reference), BarVal); 857 }); 858 } 859 860 TEST(TransferTest, MultipleParamDecls) { 861 std::string Code = R"( 862 void target(int Foo, int Bar) { 863 (void)0; 864 // [[p]] 865 } 866 )"; 867 runDataflow(Code, 868 [](llvm::ArrayRef< 869 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 870 Results, 871 ASTContext &ASTCtx) { 872 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 873 const Environment &Env = Results[0].second.Env; 874 875 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 876 ASSERT_THAT(FooDecl, NotNull()); 877 878 const StorageLocation *FooLoc = 879 Env.getStorageLocation(*FooDecl, SkipPast::None); 880 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 881 882 const Value *FooVal = Env.getValue(*FooLoc); 883 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 884 885 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 886 ASSERT_THAT(BarDecl, NotNull()); 887 888 const StorageLocation *BarLoc = 889 Env.getStorageLocation(*BarDecl, SkipPast::None); 890 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 891 892 const Value *BarVal = Env.getValue(*BarLoc); 893 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 894 }); 895 } 896 897 TEST(TransferTest, StructParamDecl) { 898 std::string Code = R"( 899 struct A { 900 int Bar; 901 }; 902 903 void target(A Foo) { 904 (void)0; 905 // [[p]] 906 } 907 )"; 908 runDataflow( 909 Code, [](llvm::ArrayRef< 910 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 911 Results, 912 ASTContext &ASTCtx) { 913 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 914 const Environment &Env = Results[0].second.Env; 915 916 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 917 ASSERT_THAT(FooDecl, NotNull()); 918 919 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 920 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 921 922 FieldDecl *BarDecl = nullptr; 923 for (FieldDecl *Field : FooFields) { 924 if (Field->getNameAsString() == "Bar") { 925 BarDecl = Field; 926 } else { 927 FAIL() << "Unexpected field: " << Field->getNameAsString(); 928 } 929 } 930 ASSERT_THAT(BarDecl, NotNull()); 931 932 const auto *FooLoc = cast<AggregateStorageLocation>( 933 Env.getStorageLocation(*FooDecl, SkipPast::None)); 934 const auto *BarLoc = 935 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 936 937 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 938 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 939 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 940 }); 941 } 942 943 TEST(TransferTest, ReferenceParamDecl) { 944 std::string Code = R"( 945 struct A {}; 946 947 void target(A &Foo) { 948 (void)0; 949 // [[p]] 950 } 951 )"; 952 runDataflow( 953 Code, [](llvm::ArrayRef< 954 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 955 Results, 956 ASTContext &ASTCtx) { 957 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 958 const Environment &Env = Results[0].second.Env; 959 960 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 961 ASSERT_THAT(FooDecl, NotNull()); 962 963 const StorageLocation *FooLoc = 964 Env.getStorageLocation(*FooDecl, SkipPast::None); 965 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 966 967 const ReferenceValue *FooVal = 968 dyn_cast<ReferenceValue>(Env.getValue(*FooLoc)); 969 ASSERT_THAT(FooVal, NotNull()); 970 971 const StorageLocation &FooReferentLoc = FooVal->getReferentLoc(); 972 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooReferentLoc)); 973 974 const Value *FooReferentVal = Env.getValue(FooReferentLoc); 975 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal)); 976 }); 977 } 978 979 TEST(TransferTest, PointerParamDecl) { 980 std::string Code = R"( 981 struct A {}; 982 983 void target(A *Foo) { 984 (void)0; 985 // [[p]] 986 } 987 )"; 988 runDataflow( 989 Code, [](llvm::ArrayRef< 990 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 991 Results, 992 ASTContext &ASTCtx) { 993 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 994 const Environment &Env = Results[0].second.Env; 995 996 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 997 ASSERT_THAT(FooDecl, NotNull()); 998 999 const StorageLocation *FooLoc = 1000 Env.getStorageLocation(*FooDecl, SkipPast::None); 1001 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 1002 1003 const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 1004 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 1005 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 1006 1007 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 1008 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 1009 }); 1010 } 1011 1012 TEST(TransferTest, StructMember) { 1013 std::string Code = R"( 1014 struct A { 1015 int Bar; 1016 }; 1017 1018 void target(A Foo) { 1019 int Baz = Foo.Bar; 1020 // [[p]] 1021 } 1022 )"; 1023 runDataflow( 1024 Code, [](llvm::ArrayRef< 1025 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1026 Results, 1027 ASTContext &ASTCtx) { 1028 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1029 const Environment &Env = Results[0].second.Env; 1030 1031 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1032 ASSERT_THAT(FooDecl, NotNull()); 1033 1034 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1035 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1036 1037 FieldDecl *BarDecl = nullptr; 1038 for (FieldDecl *Field : FooFields) { 1039 if (Field->getNameAsString() == "Bar") { 1040 BarDecl = Field; 1041 } else { 1042 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1043 } 1044 } 1045 ASSERT_THAT(BarDecl, NotNull()); 1046 1047 const auto *FooLoc = cast<AggregateStorageLocation>( 1048 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1049 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1050 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1051 1052 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1053 ASSERT_THAT(BazDecl, NotNull()); 1054 1055 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal); 1056 }); 1057 } 1058 1059 TEST(TransferTest, DerivedBaseMemberClass) { 1060 std::string Code = R"( 1061 class A { 1062 int ADefault; 1063 protected: 1064 int AProtected; 1065 private: 1066 int APrivate; 1067 public: 1068 int APublic; 1069 }; 1070 1071 class B : public A { 1072 int BDefault; 1073 protected: 1074 int BProtected; 1075 private: 1076 int BPrivate; 1077 }; 1078 1079 void target() { 1080 B Foo; 1081 // [[p]] 1082 } 1083 )"; 1084 runDataflow( 1085 Code, [](llvm::ArrayRef< 1086 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1087 Results, 1088 ASTContext &ASTCtx) { 1089 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1090 const Environment &Env = Results[0].second.Env; 1091 1092 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1093 ASSERT_THAT(FooDecl, NotNull()); 1094 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1095 1096 // Derived-class fields. 1097 const FieldDecl *BDefaultDecl = nullptr; 1098 const FieldDecl *BProtectedDecl = nullptr; 1099 const FieldDecl *BPrivateDecl = nullptr; 1100 for (const FieldDecl *Field : 1101 FooDecl->getType()->getAsRecordDecl()->fields()) { 1102 if (Field->getNameAsString() == "BDefault") { 1103 BDefaultDecl = Field; 1104 } else if (Field->getNameAsString() == "BProtected") { 1105 BProtectedDecl = Field; 1106 } else if (Field->getNameAsString() == "BPrivate") { 1107 BPrivateDecl = Field; 1108 } else { 1109 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1110 } 1111 } 1112 ASSERT_THAT(BDefaultDecl, NotNull()); 1113 ASSERT_THAT(BProtectedDecl, NotNull()); 1114 ASSERT_THAT(BPrivateDecl, NotNull()); 1115 1116 // Base-class fields. 1117 const FieldDecl *ADefaultDecl = nullptr; 1118 const FieldDecl *APrivateDecl = nullptr; 1119 const FieldDecl *AProtectedDecl = nullptr; 1120 const FieldDecl *APublicDecl = nullptr; 1121 for (const clang::CXXBaseSpecifier &Base : 1122 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1123 QualType BaseType = Base.getType(); 1124 ASSERT_TRUE(BaseType->isRecordType()); 1125 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1126 if (Field->getNameAsString() == "ADefault") { 1127 ADefaultDecl = Field; 1128 } else if (Field->getNameAsString() == "AProtected") { 1129 AProtectedDecl = Field; 1130 } else if (Field->getNameAsString() == "APrivate") { 1131 APrivateDecl = Field; 1132 } else if (Field->getNameAsString() == "APublic") { 1133 APublicDecl = Field; 1134 } else { 1135 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1136 } 1137 } 1138 } 1139 ASSERT_THAT(ADefaultDecl, NotNull()); 1140 ASSERT_THAT(AProtectedDecl, NotNull()); 1141 ASSERT_THAT(APrivateDecl, NotNull()); 1142 ASSERT_THAT(APublicDecl, NotNull()); 1143 1144 const auto &FooLoc = *cast<AggregateStorageLocation>( 1145 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1146 const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc)); 1147 1148 // Note: we can't test presence of children in `FooLoc`, because 1149 // `getChild` requires its argument be present (or fails an assert). So, 1150 // we limit to testing presence in `FooVal` and coherence between the 1151 // two. 1152 1153 // Base-class fields. 1154 EXPECT_THAT(FooVal.getChild(*ADefaultDecl), NotNull()); 1155 EXPECT_THAT(FooVal.getChild(*APrivateDecl), NotNull()); 1156 1157 EXPECT_THAT(FooVal.getChild(*AProtectedDecl), NotNull()); 1158 EXPECT_EQ(Env.getValue(FooLoc.getChild(*APublicDecl)), 1159 FooVal.getChild(*APublicDecl)); 1160 EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull()); 1161 EXPECT_EQ(Env.getValue(FooLoc.getChild(*AProtectedDecl)), 1162 FooVal.getChild(*AProtectedDecl)); 1163 1164 // Derived-class fields. 1165 EXPECT_THAT(FooVal.getChild(*BDefaultDecl), NotNull()); 1166 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BDefaultDecl)), 1167 FooVal.getChild(*BDefaultDecl)); 1168 EXPECT_THAT(FooVal.getChild(*BProtectedDecl), NotNull()); 1169 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BProtectedDecl)), 1170 FooVal.getChild(*BProtectedDecl)); 1171 EXPECT_THAT(FooVal.getChild(*BPrivateDecl), NotNull()); 1172 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BPrivateDecl)), 1173 FooVal.getChild(*BPrivateDecl)); 1174 }); 1175 } 1176 1177 static void derivedBaseMemberExpectations( 1178 llvm::ArrayRef<std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1179 Results, 1180 ASTContext &ASTCtx) { 1181 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1182 const Environment &Env = Results[0].second.Env; 1183 1184 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1185 ASSERT_THAT(FooDecl, NotNull()); 1186 1187 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1188 const FieldDecl *BarDecl = nullptr; 1189 for (const clang::CXXBaseSpecifier &Base : 1190 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1191 QualType BaseType = Base.getType(); 1192 ASSERT_TRUE(BaseType->isStructureType()); 1193 1194 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1195 if (Field->getNameAsString() == "Bar") { 1196 BarDecl = Field; 1197 } else { 1198 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1199 } 1200 } 1201 } 1202 ASSERT_THAT(BarDecl, NotNull()); 1203 1204 const auto &FooLoc = *cast<AggregateStorageLocation>( 1205 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1206 const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc)); 1207 EXPECT_THAT(FooVal.getChild(*BarDecl), NotNull()); 1208 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BarDecl)), FooVal.getChild(*BarDecl)); 1209 } 1210 1211 TEST(TransferTest, DerivedBaseMemberStructDefault) { 1212 std::string Code = R"( 1213 struct A { 1214 int Bar; 1215 }; 1216 struct B : public A { 1217 }; 1218 1219 void target() { 1220 B Foo; 1221 // [[p]] 1222 } 1223 )"; 1224 runDataflow(Code, derivedBaseMemberExpectations); 1225 } 1226 1227 TEST(TransferTest, DerivedBaseMemberPrivateFriend) { 1228 // Include an access to `Foo.Bar` to verify the analysis doesn't crash on that 1229 // access. 1230 std::string Code = R"( 1231 struct A { 1232 private: 1233 friend void target(); 1234 int Bar; 1235 }; 1236 struct B : public A { 1237 }; 1238 1239 void target() { 1240 B Foo; 1241 (void)Foo.Bar; 1242 // [[p]] 1243 } 1244 )"; 1245 runDataflow(Code, derivedBaseMemberExpectations); 1246 } 1247 1248 TEST(TransferTest, ClassMember) { 1249 std::string Code = R"( 1250 class A { 1251 public: 1252 int Bar; 1253 }; 1254 1255 void target(A Foo) { 1256 int Baz = Foo.Bar; 1257 // [[p]] 1258 } 1259 )"; 1260 runDataflow( 1261 Code, [](llvm::ArrayRef< 1262 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1263 Results, 1264 ASTContext &ASTCtx) { 1265 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1266 const Environment &Env = Results[0].second.Env; 1267 1268 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1269 ASSERT_THAT(FooDecl, NotNull()); 1270 1271 ASSERT_TRUE(FooDecl->getType()->isClassType()); 1272 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1273 1274 FieldDecl *BarDecl = nullptr; 1275 for (FieldDecl *Field : FooFields) { 1276 if (Field->getNameAsString() == "Bar") { 1277 BarDecl = Field; 1278 } else { 1279 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1280 } 1281 } 1282 ASSERT_THAT(BarDecl, NotNull()); 1283 1284 const auto *FooLoc = cast<AggregateStorageLocation>( 1285 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1286 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1287 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1288 1289 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1290 ASSERT_THAT(BazDecl, NotNull()); 1291 1292 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal); 1293 }); 1294 } 1295 1296 TEST(TransferTest, BaseClassInitializer) { 1297 using ast_matchers::cxxConstructorDecl; 1298 using ast_matchers::hasName; 1299 using ast_matchers::ofClass; 1300 1301 std::string Code = R"( 1302 class A { 1303 public: 1304 A(int I) : Bar(I) {} 1305 int Bar; 1306 }; 1307 1308 class B : public A { 1309 public: 1310 B(int I) : A(I) { 1311 (void)0; 1312 // [[p]] 1313 } 1314 }; 1315 )"; 1316 ASSERT_THAT_ERROR( 1317 test::checkDataflow<NoopAnalysis>( 1318 Code, cxxConstructorDecl(ofClass(hasName("B"))), 1319 [](ASTContext &C, Environment &) { 1320 return NoopAnalysis(C, /*ApplyBuiltinTransfer=*/true); 1321 }, 1322 [](llvm::ArrayRef< 1323 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1324 Results, 1325 ASTContext &ASTCtx) { 1326 // Regression test to verify that base-class initializers do not 1327 // trigger an assertion. If we add support for such initializers in 1328 // the future, we can expand this test to check more specific 1329 // properties. 1330 EXPECT_THAT(Results, ElementsAre(Pair("p", _))); 1331 }, 1332 {"-fsyntax-only", "-fno-delayed-template-parsing", 1333 "-std=" + std::string(LangStandard::getLangStandardForKind( 1334 LangStandard::lang_cxx17) 1335 .getName())}), 1336 llvm::Succeeded()); 1337 } 1338 1339 TEST(TransferTest, ReferenceMember) { 1340 std::string Code = R"( 1341 struct A { 1342 int &Bar; 1343 }; 1344 1345 void target(A Foo) { 1346 int Baz = Foo.Bar; 1347 // [[p]] 1348 } 1349 )"; 1350 runDataflow( 1351 Code, [](llvm::ArrayRef< 1352 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1353 Results, 1354 ASTContext &ASTCtx) { 1355 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1356 const Environment &Env = Results[0].second.Env; 1357 1358 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1359 ASSERT_THAT(FooDecl, NotNull()); 1360 1361 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1362 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1363 1364 FieldDecl *BarDecl = nullptr; 1365 for (FieldDecl *Field : FooFields) { 1366 if (Field->getNameAsString() == "Bar") { 1367 BarDecl = Field; 1368 } else { 1369 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1370 } 1371 } 1372 ASSERT_THAT(BarDecl, NotNull()); 1373 1374 const auto *FooLoc = cast<AggregateStorageLocation>( 1375 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1376 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1377 const auto *BarVal = cast<ReferenceValue>(FooVal->getChild(*BarDecl)); 1378 const auto *BarReferentVal = 1379 cast<IntegerValue>(Env.getValue(BarVal->getReferentLoc())); 1380 1381 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1382 ASSERT_THAT(BazDecl, NotNull()); 1383 1384 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarReferentVal); 1385 }); 1386 } 1387 1388 TEST(TransferTest, StructThisMember) { 1389 std::string Code = R"( 1390 struct A { 1391 int Bar; 1392 1393 struct B { 1394 int Baz; 1395 }; 1396 1397 B Qux; 1398 1399 void target() { 1400 int Foo = Bar; 1401 int Quux = Qux.Baz; 1402 // [[p]] 1403 } 1404 }; 1405 )"; 1406 runDataflow( 1407 Code, [](llvm::ArrayRef< 1408 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1409 Results, 1410 ASTContext &ASTCtx) { 1411 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1412 const Environment &Env = Results[0].second.Env; 1413 1414 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1415 Env.getThisPointeeStorageLocation()); 1416 ASSERT_THAT(ThisLoc, NotNull()); 1417 1418 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1419 ASSERT_THAT(BarDecl, NotNull()); 1420 1421 const auto *BarLoc = 1422 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1423 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1424 1425 const Value *BarVal = Env.getValue(*BarLoc); 1426 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1427 1428 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1429 ASSERT_THAT(FooDecl, NotNull()); 1430 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1431 1432 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1433 ASSERT_THAT(QuxDecl, NotNull()); 1434 1435 ASSERT_TRUE(QuxDecl->getType()->isStructureType()); 1436 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1437 1438 FieldDecl *BazDecl = nullptr; 1439 for (FieldDecl *Field : QuxFields) { 1440 if (Field->getNameAsString() == "Baz") { 1441 BazDecl = Field; 1442 } else { 1443 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1444 } 1445 } 1446 ASSERT_THAT(BazDecl, NotNull()); 1447 1448 const auto *QuxLoc = 1449 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1450 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1451 ASSERT_THAT(QuxVal, NotNull()); 1452 1453 const auto *BazLoc = 1454 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1455 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1456 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1457 1458 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1459 ASSERT_THAT(QuuxDecl, NotNull()); 1460 EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal); 1461 }); 1462 } 1463 1464 TEST(TransferTest, ClassThisMember) { 1465 std::string Code = R"( 1466 class A { 1467 int Bar; 1468 1469 class B { 1470 public: 1471 int Baz; 1472 }; 1473 1474 B Qux; 1475 1476 void target() { 1477 int Foo = Bar; 1478 int Quux = Qux.Baz; 1479 // [[p]] 1480 } 1481 }; 1482 )"; 1483 runDataflow( 1484 Code, [](llvm::ArrayRef< 1485 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1486 Results, 1487 ASTContext &ASTCtx) { 1488 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1489 const Environment &Env = Results[0].second.Env; 1490 1491 const auto *ThisLoc = 1492 cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation()); 1493 1494 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1495 ASSERT_THAT(BarDecl, NotNull()); 1496 1497 const auto *BarLoc = 1498 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1499 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1500 1501 const Value *BarVal = Env.getValue(*BarLoc); 1502 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1503 1504 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1505 ASSERT_THAT(FooDecl, NotNull()); 1506 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1507 1508 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1509 ASSERT_THAT(QuxDecl, NotNull()); 1510 1511 ASSERT_TRUE(QuxDecl->getType()->isClassType()); 1512 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1513 1514 FieldDecl *BazDecl = nullptr; 1515 for (FieldDecl *Field : QuxFields) { 1516 if (Field->getNameAsString() == "Baz") { 1517 BazDecl = Field; 1518 } else { 1519 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1520 } 1521 } 1522 ASSERT_THAT(BazDecl, NotNull()); 1523 1524 const auto *QuxLoc = 1525 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1526 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1527 ASSERT_THAT(QuxVal, NotNull()); 1528 1529 const auto *BazLoc = 1530 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1531 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1532 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1533 1534 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1535 ASSERT_THAT(QuuxDecl, NotNull()); 1536 EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal); 1537 }); 1538 } 1539 1540 TEST(TransferTest, StructThisInLambda) { 1541 std::string ThisCaptureCode = R"( 1542 struct A { 1543 void frob() { 1544 [this]() { 1545 int Foo = Bar; 1546 // [[p1]] 1547 }(); 1548 } 1549 1550 int Bar; 1551 }; 1552 )"; 1553 runDataflow( 1554 ThisCaptureCode, 1555 [](llvm::ArrayRef< 1556 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1557 Results, 1558 ASTContext &ASTCtx) { 1559 ASSERT_THAT(Results, ElementsAre(Pair("p1", _))); 1560 const Environment &Env = Results[0].second.Env; 1561 1562 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1563 Env.getThisPointeeStorageLocation()); 1564 ASSERT_THAT(ThisLoc, NotNull()); 1565 1566 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1567 ASSERT_THAT(BarDecl, NotNull()); 1568 1569 const auto *BarLoc = 1570 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1571 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1572 1573 const Value *BarVal = Env.getValue(*BarLoc); 1574 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1575 1576 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1577 ASSERT_THAT(FooDecl, NotNull()); 1578 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1579 }, 1580 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1581 1582 std::string RefCaptureDefaultCode = R"( 1583 struct A { 1584 void frob() { 1585 [&]() { 1586 int Foo = Bar; 1587 // [[p2]] 1588 }(); 1589 } 1590 1591 int Bar; 1592 }; 1593 )"; 1594 runDataflow( 1595 RefCaptureDefaultCode, 1596 [](llvm::ArrayRef< 1597 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1598 Results, 1599 ASTContext &ASTCtx) { 1600 ASSERT_THAT(Results, ElementsAre(Pair("p2", _))); 1601 const Environment &Env = Results[0].second.Env; 1602 1603 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1604 Env.getThisPointeeStorageLocation()); 1605 ASSERT_THAT(ThisLoc, NotNull()); 1606 1607 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1608 ASSERT_THAT(BarDecl, NotNull()); 1609 1610 const auto *BarLoc = 1611 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1612 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1613 1614 const Value *BarVal = Env.getValue(*BarLoc); 1615 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1616 1617 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1618 ASSERT_THAT(FooDecl, NotNull()); 1619 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1620 }, 1621 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1622 1623 std::string FreeFunctionLambdaCode = R"( 1624 void foo() { 1625 int Bar; 1626 [&]() { 1627 int Foo = Bar; 1628 // [[p3]] 1629 }(); 1630 } 1631 )"; 1632 runDataflow( 1633 FreeFunctionLambdaCode, 1634 [](llvm::ArrayRef< 1635 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1636 Results, 1637 ASTContext &ASTCtx) { 1638 ASSERT_THAT(Results, ElementsAre(Pair("p3", _))); 1639 const Environment &Env = Results[0].second.Env; 1640 1641 EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull()); 1642 }, 1643 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1644 } 1645 1646 TEST(TransferTest, ConstructorInitializer) { 1647 std::string Code = R"( 1648 struct target { 1649 int Bar; 1650 1651 target(int Foo) : Bar(Foo) { 1652 int Qux = Bar; 1653 // [[p]] 1654 } 1655 }; 1656 )"; 1657 runDataflow(Code, 1658 [](llvm::ArrayRef< 1659 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1660 Results, 1661 ASTContext &ASTCtx) { 1662 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1663 const Environment &Env = Results[0].second.Env; 1664 1665 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1666 Env.getThisPointeeStorageLocation()); 1667 ASSERT_THAT(ThisLoc, NotNull()); 1668 1669 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1670 ASSERT_THAT(FooDecl, NotNull()); 1671 1672 const auto *FooVal = 1673 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1674 1675 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1676 ASSERT_THAT(QuxDecl, NotNull()); 1677 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1678 }); 1679 } 1680 1681 TEST(TransferTest, DefaultInitializer) { 1682 std::string Code = R"( 1683 struct target { 1684 int Bar; 1685 int Baz = Bar; 1686 1687 target(int Foo) : Bar(Foo) { 1688 int Qux = Baz; 1689 // [[p]] 1690 } 1691 }; 1692 )"; 1693 runDataflow(Code, 1694 [](llvm::ArrayRef< 1695 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1696 Results, 1697 ASTContext &ASTCtx) { 1698 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1699 const Environment &Env = Results[0].second.Env; 1700 1701 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1702 Env.getThisPointeeStorageLocation()); 1703 ASSERT_THAT(ThisLoc, NotNull()); 1704 1705 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1706 ASSERT_THAT(FooDecl, NotNull()); 1707 1708 const auto *FooVal = 1709 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1710 1711 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1712 ASSERT_THAT(QuxDecl, NotNull()); 1713 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1714 }); 1715 } 1716 1717 TEST(TransferTest, DefaultInitializerReference) { 1718 std::string Code = R"( 1719 struct target { 1720 int &Bar; 1721 int &Baz = Bar; 1722 1723 target(int &Foo) : Bar(Foo) { 1724 int &Qux = Baz; 1725 // [[p]] 1726 } 1727 }; 1728 )"; 1729 runDataflow( 1730 Code, [](llvm::ArrayRef< 1731 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1732 Results, 1733 ASTContext &ASTCtx) { 1734 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1735 const Environment &Env = Results[0].second.Env; 1736 1737 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1738 Env.getThisPointeeStorageLocation()); 1739 ASSERT_THAT(ThisLoc, NotNull()); 1740 1741 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1742 ASSERT_THAT(FooDecl, NotNull()); 1743 1744 const auto *FooVal = 1745 cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None)); 1746 1747 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1748 ASSERT_THAT(QuxDecl, NotNull()); 1749 1750 const auto *QuxVal = 1751 cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None)); 1752 EXPECT_EQ(&QuxVal->getReferentLoc(), &FooVal->getReferentLoc()); 1753 }); 1754 } 1755 1756 TEST(TransferTest, TemporaryObject) { 1757 std::string Code = R"( 1758 struct A { 1759 int Bar; 1760 }; 1761 1762 void target() { 1763 A Foo = A(); 1764 // [[p]] 1765 } 1766 )"; 1767 runDataflow( 1768 Code, [](llvm::ArrayRef< 1769 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1770 Results, 1771 ASTContext &ASTCtx) { 1772 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1773 const Environment &Env = Results[0].second.Env; 1774 1775 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1776 ASSERT_THAT(FooDecl, NotNull()); 1777 1778 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1779 ASSERT_THAT(BarDecl, NotNull()); 1780 1781 const auto *FooLoc = cast<AggregateStorageLocation>( 1782 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1783 const auto *BarLoc = 1784 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1785 1786 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1787 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1788 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1789 }); 1790 } 1791 1792 TEST(TransferTest, ElidableConstructor) { 1793 // This test is effectively the same as TransferTest.TemporaryObject, but 1794 // the code is compiled as C++ 14. 1795 std::string Code = R"( 1796 struct A { 1797 int Bar; 1798 }; 1799 1800 void target() { 1801 A Foo = A(); 1802 // [[p]] 1803 } 1804 )"; 1805 runDataflow( 1806 Code, 1807 [](llvm::ArrayRef< 1808 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1809 Results, 1810 ASTContext &ASTCtx) { 1811 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1812 const Environment &Env = Results[0].second.Env; 1813 1814 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1815 ASSERT_THAT(FooDecl, NotNull()); 1816 1817 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1818 ASSERT_THAT(BarDecl, NotNull()); 1819 1820 const auto *FooLoc = cast<AggregateStorageLocation>( 1821 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1822 const auto *BarLoc = 1823 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1824 1825 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1826 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1827 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1828 }, 1829 LangStandard::lang_cxx14); 1830 } 1831 1832 TEST(TransferTest, AssignmentOperator) { 1833 std::string Code = R"( 1834 struct A { 1835 int Baz; 1836 }; 1837 1838 void target() { 1839 A Foo; 1840 A Bar; 1841 // [[p1]] 1842 Foo = Bar; 1843 // [[p2]] 1844 } 1845 )"; 1846 runDataflow( 1847 Code, [](llvm::ArrayRef< 1848 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1849 Results, 1850 ASTContext &ASTCtx) { 1851 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 1852 const Environment &Env1 = Results[0].second.Env; 1853 const Environment &Env2 = Results[1].second.Env; 1854 1855 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1856 ASSERT_THAT(FooDecl, NotNull()); 1857 1858 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1859 ASSERT_THAT(BarDecl, NotNull()); 1860 1861 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1862 ASSERT_THAT(BazDecl, NotNull()); 1863 1864 const auto *FooLoc1 = cast<AggregateStorageLocation>( 1865 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 1866 const auto *BarLoc1 = cast<AggregateStorageLocation>( 1867 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 1868 1869 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 1870 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 1871 EXPECT_NE(FooVal1, BarVal1); 1872 1873 const auto *FooBazVal1 = 1874 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 1875 const auto *BarBazVal1 = 1876 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 1877 EXPECT_NE(FooBazVal1, BarBazVal1); 1878 1879 const auto *FooLoc2 = cast<AggregateStorageLocation>( 1880 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 1881 const auto *BarLoc2 = cast<AggregateStorageLocation>( 1882 Env2.getStorageLocation(*BarDecl, SkipPast::None)); 1883 1884 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 1885 const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2)); 1886 EXPECT_EQ(FooVal2, BarVal2); 1887 1888 const auto *FooBazVal2 = 1889 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 1890 const auto *BarBazVal2 = 1891 cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl))); 1892 EXPECT_EQ(FooBazVal2, BarBazVal2); 1893 }); 1894 } 1895 1896 TEST(TransferTest, CopyConstructor) { 1897 std::string Code = R"( 1898 struct A { 1899 int Baz; 1900 }; 1901 1902 void target() { 1903 A Foo; 1904 A Bar = Foo; 1905 // [[p]] 1906 } 1907 )"; 1908 runDataflow( 1909 Code, [](llvm::ArrayRef< 1910 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1911 Results, 1912 ASTContext &ASTCtx) { 1913 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1914 const Environment &Env = Results[0].second.Env; 1915 1916 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1917 ASSERT_THAT(FooDecl, NotNull()); 1918 1919 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1920 ASSERT_THAT(BarDecl, NotNull()); 1921 1922 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1923 ASSERT_THAT(BazDecl, NotNull()); 1924 1925 const auto *FooLoc = cast<AggregateStorageLocation>( 1926 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1927 const auto *BarLoc = cast<AggregateStorageLocation>( 1928 Env.getStorageLocation(*BarDecl, SkipPast::None)); 1929 1930 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1931 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 1932 EXPECT_EQ(FooVal, BarVal); 1933 1934 const auto *FooBazVal = 1935 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 1936 const auto *BarBazVal = 1937 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 1938 EXPECT_EQ(FooBazVal, BarBazVal); 1939 }); 1940 } 1941 1942 TEST(TransferTest, CopyConstructorWithParens) { 1943 std::string Code = R"( 1944 struct A { 1945 int Baz; 1946 }; 1947 1948 void target() { 1949 A Foo; 1950 A Bar((A(Foo))); 1951 // [[p]] 1952 } 1953 )"; 1954 runDataflow( 1955 Code, [](llvm::ArrayRef< 1956 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1957 Results, 1958 ASTContext &ASTCtx) { 1959 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1960 const Environment &Env = Results[0].second.Env; 1961 1962 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1963 ASSERT_THAT(FooDecl, NotNull()); 1964 1965 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1966 ASSERT_THAT(BarDecl, NotNull()); 1967 1968 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1969 ASSERT_THAT(BazDecl, NotNull()); 1970 1971 const auto *FooLoc = cast<AggregateStorageLocation>( 1972 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1973 const auto *BarLoc = cast<AggregateStorageLocation>( 1974 Env.getStorageLocation(*BarDecl, SkipPast::None)); 1975 1976 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1977 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 1978 EXPECT_EQ(FooVal, BarVal); 1979 1980 const auto *FooBazVal = 1981 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 1982 const auto *BarBazVal = 1983 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 1984 EXPECT_EQ(FooBazVal, BarBazVal); 1985 }); 1986 } 1987 1988 TEST(TransferTest, MoveConstructor) { 1989 std::string Code = R"( 1990 namespace std { 1991 1992 template <typename T> struct remove_reference { using type = T; }; 1993 template <typename T> struct remove_reference<T&> { using type = T; }; 1994 template <typename T> struct remove_reference<T&&> { using type = T; }; 1995 1996 template <typename T> 1997 using remove_reference_t = typename remove_reference<T>::type; 1998 1999 template <typename T> 2000 std::remove_reference_t<T>&& move(T&& x); 2001 2002 } // namespace std 2003 2004 struct A { 2005 int Baz; 2006 }; 2007 2008 void target() { 2009 A Foo; 2010 A Bar; 2011 // [[p1]] 2012 Foo = std::move(Bar); 2013 // [[p2]] 2014 } 2015 )"; 2016 runDataflow( 2017 Code, [](llvm::ArrayRef< 2018 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2019 Results, 2020 ASTContext &ASTCtx) { 2021 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 2022 const Environment &Env1 = Results[0].second.Env; 2023 const Environment &Env2 = Results[1].second.Env; 2024 2025 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2026 ASSERT_THAT(FooDecl, NotNull()); 2027 2028 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2029 ASSERT_THAT(BarDecl, NotNull()); 2030 2031 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2032 ASSERT_THAT(BazDecl, NotNull()); 2033 2034 const auto *FooLoc1 = cast<AggregateStorageLocation>( 2035 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 2036 const auto *BarLoc1 = cast<AggregateStorageLocation>( 2037 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 2038 2039 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 2040 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 2041 EXPECT_NE(FooVal1, BarVal1); 2042 2043 const auto *FooBazVal1 = 2044 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 2045 const auto *BarBazVal1 = 2046 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 2047 EXPECT_NE(FooBazVal1, BarBazVal1); 2048 2049 const auto *FooLoc2 = cast<AggregateStorageLocation>( 2050 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 2051 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 2052 EXPECT_EQ(FooVal2, BarVal1); 2053 2054 const auto *FooBazVal2 = 2055 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 2056 EXPECT_EQ(FooBazVal2, BarBazVal1); 2057 }); 2058 } 2059 2060 TEST(TransferTest, BindTemporary) { 2061 std::string Code = R"( 2062 struct A { 2063 virtual ~A() = default; 2064 2065 int Baz; 2066 }; 2067 2068 void target(A Foo) { 2069 int Bar = A(Foo).Baz; 2070 // [[p]] 2071 } 2072 )"; 2073 runDataflow(Code, 2074 [](llvm::ArrayRef< 2075 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2076 Results, 2077 ASTContext &ASTCtx) { 2078 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2079 const Environment &Env = Results[0].second.Env; 2080 2081 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2082 ASSERT_THAT(FooDecl, NotNull()); 2083 2084 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2085 ASSERT_THAT(BarDecl, NotNull()); 2086 2087 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2088 ASSERT_THAT(BazDecl, NotNull()); 2089 2090 const auto &FooVal = 2091 *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 2092 const auto *BarVal = 2093 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2094 EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl)); 2095 }); 2096 } 2097 2098 TEST(TransferTest, StaticCast) { 2099 std::string Code = R"( 2100 void target(int Foo) { 2101 int Bar = static_cast<int>(Foo); 2102 // [[p]] 2103 } 2104 )"; 2105 runDataflow(Code, 2106 [](llvm::ArrayRef< 2107 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2108 Results, 2109 ASTContext &ASTCtx) { 2110 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2111 const Environment &Env = Results[0].second.Env; 2112 2113 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2114 ASSERT_THAT(FooDecl, NotNull()); 2115 2116 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2117 ASSERT_THAT(BarDecl, NotNull()); 2118 2119 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2120 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2121 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2122 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2123 EXPECT_EQ(FooVal, BarVal); 2124 }); 2125 } 2126 2127 TEST(TransferTest, IntegralCast) { 2128 std::string Code = R"( 2129 void target(int Foo) { 2130 long Bar = Foo; 2131 // [[p]] 2132 } 2133 )"; 2134 runDataflow(Code, 2135 [](llvm::ArrayRef< 2136 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2137 Results, 2138 ASTContext &ASTCtx) { 2139 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2140 const Environment &Env = Results[0].second.Env; 2141 2142 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2143 ASSERT_THAT(FooDecl, NotNull()); 2144 2145 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2146 ASSERT_THAT(BarDecl, NotNull()); 2147 2148 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2149 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2150 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2151 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2152 EXPECT_EQ(FooVal, BarVal); 2153 }); 2154 } 2155 2156 TEST(TransferTest, IntegraltoBooleanCast) { 2157 std::string Code = R"( 2158 void target(int Foo) { 2159 bool Bar = Foo; 2160 // [[p]] 2161 } 2162 )"; 2163 runDataflow(Code, 2164 [](llvm::ArrayRef< 2165 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2166 Results, 2167 ASTContext &ASTCtx) { 2168 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2169 const Environment &Env = Results[0].second.Env; 2170 2171 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2172 ASSERT_THAT(FooDecl, NotNull()); 2173 2174 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2175 ASSERT_THAT(BarDecl, NotNull()); 2176 2177 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2178 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2179 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2180 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2181 }); 2182 } 2183 2184 TEST(TransferTest, IntegralToBooleanCastFromBool) { 2185 std::string Code = R"( 2186 void target(bool Foo) { 2187 int Zab = Foo; 2188 bool Bar = Zab; 2189 // [[p]] 2190 } 2191 )"; 2192 runDataflow(Code, 2193 [](llvm::ArrayRef< 2194 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2195 Results, 2196 ASTContext &ASTCtx) { 2197 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2198 const Environment &Env = Results[0].second.Env; 2199 2200 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2201 ASSERT_THAT(FooDecl, NotNull()); 2202 2203 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2204 ASSERT_THAT(BarDecl, NotNull()); 2205 2206 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2207 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2208 EXPECT_TRUE(isa<BoolValue>(FooVal)); 2209 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2210 EXPECT_EQ(FooVal, BarVal); 2211 }); 2212 } 2213 2214 TEST(TransferTest, NullToPointerCast) { 2215 std::string Code = R"( 2216 struct Baz {}; 2217 void target() { 2218 int *FooX = nullptr; 2219 int *FooY = nullptr; 2220 bool **Bar = nullptr; 2221 Baz *Baz = nullptr; 2222 // [[p]] 2223 } 2224 )"; 2225 runDataflow(Code, 2226 [](llvm::ArrayRef< 2227 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2228 Results, 2229 ASTContext &ASTCtx) { 2230 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2231 const Environment &Env = Results[0].second.Env; 2232 2233 const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX"); 2234 ASSERT_THAT(FooXDecl, NotNull()); 2235 2236 const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY"); 2237 ASSERT_THAT(FooYDecl, NotNull()); 2238 2239 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2240 ASSERT_THAT(BarDecl, NotNull()); 2241 2242 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2243 ASSERT_THAT(BazDecl, NotNull()); 2244 2245 const auto *FooXVal = 2246 cast<PointerValue>(Env.getValue(*FooXDecl, SkipPast::None)); 2247 const auto *FooYVal = 2248 cast<PointerValue>(Env.getValue(*FooYDecl, SkipPast::None)); 2249 const auto *BarVal = 2250 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2251 const auto *BazVal = 2252 cast<PointerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2253 2254 EXPECT_EQ(FooXVal, FooYVal); 2255 EXPECT_NE(FooXVal, BarVal); 2256 EXPECT_NE(FooXVal, BazVal); 2257 EXPECT_NE(BarVal, BazVal); 2258 2259 const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc(); 2260 EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc)); 2261 EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull()); 2262 2263 const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc(); 2264 EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc)); 2265 EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull()); 2266 2267 const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc(); 2268 EXPECT_TRUE(isa<AggregateStorageLocation>(BazPointeeLoc)); 2269 EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull()); 2270 }); 2271 } 2272 2273 TEST(TransferTest, NullToMemberPointerCast) { 2274 std::string Code = R"( 2275 struct Foo {}; 2276 void target(Foo *Foo) { 2277 int Foo::*MemberPointer = nullptr; 2278 // [[p]] 2279 } 2280 )"; 2281 runDataflow( 2282 Code, [](llvm::ArrayRef< 2283 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2284 Results, 2285 ASTContext &ASTCtx) { 2286 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2287 const Environment &Env = Results[0].second.Env; 2288 2289 const ValueDecl *MemberPointerDecl = 2290 findValueDecl(ASTCtx, "MemberPointer"); 2291 ASSERT_THAT(MemberPointerDecl, NotNull()); 2292 2293 const auto *MemberPointerVal = cast<PointerValue>( 2294 Env.getValue(*MemberPointerDecl, SkipPast::None)); 2295 2296 const StorageLocation &MemberLoc = MemberPointerVal->getPointeeLoc(); 2297 EXPECT_THAT(Env.getValue(MemberLoc), IsNull()); 2298 }); 2299 } 2300 2301 TEST(TransferTest, AddrOfValue) { 2302 std::string Code = R"( 2303 void target() { 2304 int Foo; 2305 int *Bar = &Foo; 2306 // [[p]] 2307 } 2308 )"; 2309 runDataflow(Code, 2310 [](llvm::ArrayRef< 2311 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2312 Results, 2313 ASTContext &ASTCtx) { 2314 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2315 const Environment &Env = Results[0].second.Env; 2316 2317 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2318 ASSERT_THAT(FooDecl, NotNull()); 2319 2320 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2321 ASSERT_THAT(BarDecl, NotNull()); 2322 2323 const auto *FooLoc = cast<ScalarStorageLocation>( 2324 Env.getStorageLocation(*FooDecl, SkipPast::None)); 2325 const auto *BarVal = 2326 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2327 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc); 2328 }); 2329 } 2330 2331 TEST(TransferTest, AddrOfReference) { 2332 std::string Code = R"( 2333 void target(int *Foo) { 2334 int *Bar = &(*Foo); 2335 // [[p]] 2336 } 2337 )"; 2338 runDataflow(Code, 2339 [](llvm::ArrayRef< 2340 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2341 Results, 2342 ASTContext &ASTCtx) { 2343 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2344 const Environment &Env = Results[0].second.Env; 2345 2346 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2347 ASSERT_THAT(FooDecl, NotNull()); 2348 2349 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2350 ASSERT_THAT(BarDecl, NotNull()); 2351 2352 const auto *FooVal = 2353 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2354 const auto *BarVal = 2355 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2356 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 2357 }); 2358 } 2359 2360 TEST(TransferTest, DerefDependentPtr) { 2361 std::string Code = R"( 2362 template <typename T> 2363 void target(T *Foo) { 2364 T &Bar = *Foo; 2365 /*[[p]]*/ 2366 } 2367 )"; 2368 runDataflow( 2369 Code, [](llvm::ArrayRef< 2370 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2371 Results, 2372 ASTContext &ASTCtx) { 2373 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2374 const Environment &Env = Results[0].second.Env; 2375 2376 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2377 ASSERT_THAT(FooDecl, NotNull()); 2378 2379 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2380 ASSERT_THAT(BarDecl, NotNull()); 2381 2382 const auto *FooVal = 2383 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2384 const auto *BarVal = 2385 cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None)); 2386 EXPECT_EQ(&BarVal->getReferentLoc(), &FooVal->getPointeeLoc()); 2387 }); 2388 } 2389 2390 TEST(TransferTest, VarDeclInitAssignConditionalOperator) { 2391 std::string Code = R"( 2392 struct A {}; 2393 2394 void target(A Foo, A Bar, bool Cond) { 2395 A Baz = Cond ? Foo : Bar; 2396 /*[[p]]*/ 2397 } 2398 )"; 2399 runDataflow( 2400 Code, [](llvm::ArrayRef< 2401 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2402 Results, 2403 ASTContext &ASTCtx) { 2404 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2405 const Environment &Env = Results[0].second.Env; 2406 2407 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2408 ASSERT_THAT(FooDecl, NotNull()); 2409 2410 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2411 ASSERT_THAT(BarDecl, NotNull()); 2412 2413 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2414 ASSERT_THAT(BazDecl, NotNull()); 2415 2416 const auto *FooVal = 2417 cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 2418 const auto *BarVal = 2419 cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None)); 2420 2421 const auto *BazVal = 2422 dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None)); 2423 ASSERT_THAT(BazVal, NotNull()); 2424 2425 EXPECT_NE(BazVal, FooVal); 2426 EXPECT_NE(BazVal, BarVal); 2427 }); 2428 } 2429 2430 TEST(TransferTest, VarDeclInDoWhile) { 2431 std::string Code = R"( 2432 void target(int *Foo) { 2433 do { 2434 int Bar = *Foo; 2435 } while (true); 2436 (void)0; 2437 /*[[p]]*/ 2438 } 2439 )"; 2440 runDataflow(Code, 2441 [](llvm::ArrayRef< 2442 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2443 Results, 2444 ASTContext &ASTCtx) { 2445 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2446 const Environment &Env = Results[0].second.Env; 2447 2448 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2449 ASSERT_THAT(FooDecl, NotNull()); 2450 2451 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2452 ASSERT_THAT(BarDecl, NotNull()); 2453 2454 const auto *FooVal = 2455 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2456 const auto *FooPointeeVal = 2457 cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc())); 2458 2459 const auto *BarVal = dyn_cast_or_null<IntegerValue>( 2460 Env.getValue(*BarDecl, SkipPast::None)); 2461 ASSERT_THAT(BarVal, NotNull()); 2462 2463 EXPECT_EQ(BarVal, FooPointeeVal); 2464 }); 2465 } 2466 2467 TEST(TransferTest, AggregateInitialization) { 2468 std::string BracesCode = R"( 2469 struct A { 2470 int Foo; 2471 }; 2472 2473 struct B { 2474 int Bar; 2475 A Baz; 2476 int Qux; 2477 }; 2478 2479 void target(int BarArg, int FooArg, int QuxArg) { 2480 B Quux{BarArg, {FooArg}, QuxArg}; 2481 /*[[p]]*/ 2482 } 2483 )"; 2484 std::string BraceEllisionCode = R"( 2485 struct A { 2486 int Foo; 2487 }; 2488 2489 struct B { 2490 int Bar; 2491 A Baz; 2492 int Qux; 2493 }; 2494 2495 void target(int BarArg, int FooArg, int QuxArg) { 2496 B Quux = {BarArg, FooArg, QuxArg}; 2497 /*[[p]]*/ 2498 } 2499 )"; 2500 for (const std::string &Code : {BracesCode, BraceEllisionCode}) { 2501 runDataflow( 2502 Code, [](llvm::ArrayRef< 2503 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2504 Results, 2505 ASTContext &ASTCtx) { 2506 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2507 const Environment &Env = Results[0].second.Env; 2508 2509 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2510 ASSERT_THAT(FooDecl, 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 *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2519 ASSERT_THAT(QuxDecl, NotNull()); 2520 2521 const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg"); 2522 ASSERT_THAT(FooArgDecl, NotNull()); 2523 2524 const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg"); 2525 ASSERT_THAT(BarArgDecl, NotNull()); 2526 2527 const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg"); 2528 ASSERT_THAT(QuxArgDecl, NotNull()); 2529 2530 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 2531 ASSERT_THAT(QuuxDecl, NotNull()); 2532 2533 const auto *FooArgVal = 2534 cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None)); 2535 const auto *BarArgVal = 2536 cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None)); 2537 const auto *QuxArgVal = 2538 cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None)); 2539 2540 const auto *QuuxVal = 2541 cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None)); 2542 ASSERT_THAT(QuuxVal, NotNull()); 2543 2544 const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl)); 2545 ASSERT_THAT(BazVal, NotNull()); 2546 2547 EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal); 2548 EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal); 2549 EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal); 2550 }); 2551 } 2552 } 2553 2554 TEST(TransferTest, AssignToUnionMember) { 2555 std::string Code = R"( 2556 union A { 2557 int Foo; 2558 }; 2559 2560 void target(int Bar) { 2561 A Baz; 2562 Baz.Foo = Bar; 2563 // [[p]] 2564 } 2565 )"; 2566 runDataflow(Code, 2567 [](llvm::ArrayRef< 2568 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2569 Results, 2570 ASTContext &ASTCtx) { 2571 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2572 const Environment &Env = Results[0].second.Env; 2573 2574 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2575 ASSERT_THAT(BazDecl, NotNull()); 2576 ASSERT_TRUE(BazDecl->getType()->isUnionType()); 2577 2578 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>( 2579 Env.getStorageLocation(*BazDecl, SkipPast::None)); 2580 ASSERT_THAT(BazLoc, NotNull()); 2581 2582 // FIXME: Add support for union types. 2583 EXPECT_THAT(Env.getValue(*BazLoc), IsNull()); 2584 }); 2585 } 2586 2587 TEST(TransferTest, AssignFromBoolLiteral) { 2588 std::string Code = R"( 2589 void target() { 2590 bool Foo = true; 2591 bool Bar = false; 2592 // [[p]] 2593 } 2594 )"; 2595 runDataflow(Code, 2596 [](llvm::ArrayRef< 2597 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2598 Results, 2599 ASTContext &ASTCtx) { 2600 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2601 const Environment &Env = Results[0].second.Env; 2602 2603 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2604 ASSERT_THAT(FooDecl, NotNull()); 2605 2606 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2607 Env.getValue(*FooDecl, SkipPast::None)); 2608 ASSERT_THAT(FooVal, NotNull()); 2609 2610 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2611 ASSERT_THAT(BarDecl, NotNull()); 2612 2613 const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>( 2614 Env.getValue(*BarDecl, SkipPast::None)); 2615 ASSERT_THAT(BarVal, NotNull()); 2616 2617 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true)); 2618 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false)); 2619 }); 2620 } 2621 2622 TEST(TransferTest, AssignFromCompositeBoolExpression) { 2623 { 2624 std::string Code = R"( 2625 void target(bool Foo, bool Bar, bool Qux) { 2626 bool Baz = (Foo) && (Bar || Qux); 2627 // [[p]] 2628 } 2629 )"; 2630 runDataflow( 2631 Code, [](llvm::ArrayRef< 2632 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2633 Results, 2634 ASTContext &ASTCtx) { 2635 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2636 const Environment &Env = Results[0].second.Env; 2637 2638 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2639 ASSERT_THAT(FooDecl, NotNull()); 2640 2641 const auto *FooVal = dyn_cast_or_null<BoolValue>( 2642 Env.getValue(*FooDecl, SkipPast::None)); 2643 ASSERT_THAT(FooVal, NotNull()); 2644 2645 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2646 ASSERT_THAT(BarDecl, NotNull()); 2647 2648 const auto *BarVal = dyn_cast_or_null<BoolValue>( 2649 Env.getValue(*BarDecl, SkipPast::None)); 2650 ASSERT_THAT(BarVal, NotNull()); 2651 2652 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2653 ASSERT_THAT(QuxDecl, NotNull()); 2654 2655 const auto *QuxVal = dyn_cast_or_null<BoolValue>( 2656 Env.getValue(*QuxDecl, SkipPast::None)); 2657 ASSERT_THAT(QuxVal, NotNull()); 2658 2659 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2660 ASSERT_THAT(BazDecl, NotNull()); 2661 2662 const auto *BazVal = dyn_cast_or_null<ConjunctionValue>( 2663 Env.getValue(*BazDecl, SkipPast::None)); 2664 ASSERT_THAT(BazVal, NotNull()); 2665 EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal); 2666 2667 const auto *BazRightSubValVal = 2668 cast<DisjunctionValue>(&BazVal->getRightSubValue()); 2669 EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal); 2670 EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal); 2671 }); 2672 } 2673 2674 { 2675 std::string Code = R"( 2676 void target(bool Foo, bool Bar, bool Qux) { 2677 bool Baz = (Foo && Qux) || (Bar); 2678 // [[p]] 2679 } 2680 )"; 2681 runDataflow( 2682 Code, [](llvm::ArrayRef< 2683 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2684 Results, 2685 ASTContext &ASTCtx) { 2686 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2687 const Environment &Env = Results[0].second.Env; 2688 2689 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2690 ASSERT_THAT(FooDecl, NotNull()); 2691 2692 const auto *FooVal = dyn_cast_or_null<BoolValue>( 2693 Env.getValue(*FooDecl, SkipPast::None)); 2694 ASSERT_THAT(FooVal, NotNull()); 2695 2696 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2697 ASSERT_THAT(BarDecl, NotNull()); 2698 2699 const auto *BarVal = dyn_cast_or_null<BoolValue>( 2700 Env.getValue(*BarDecl, SkipPast::None)); 2701 ASSERT_THAT(BarVal, NotNull()); 2702 2703 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2704 ASSERT_THAT(QuxDecl, NotNull()); 2705 2706 const auto *QuxVal = dyn_cast_or_null<BoolValue>( 2707 Env.getValue(*QuxDecl, SkipPast::None)); 2708 ASSERT_THAT(QuxVal, NotNull()); 2709 2710 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2711 ASSERT_THAT(BazDecl, NotNull()); 2712 2713 const auto *BazVal = dyn_cast_or_null<DisjunctionValue>( 2714 Env.getValue(*BazDecl, SkipPast::None)); 2715 ASSERT_THAT(BazVal, NotNull()); 2716 2717 const auto *BazLeftSubValVal = 2718 cast<ConjunctionValue>(&BazVal->getLeftSubValue()); 2719 EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal); 2720 EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal); 2721 2722 EXPECT_EQ(&BazVal->getRightSubValue(), BarVal); 2723 }); 2724 } 2725 2726 { 2727 std::string Code = R"( 2728 void target(bool A, bool B, bool C, bool D) { 2729 bool Foo = ((A && B) && C) && D; 2730 // [[p]] 2731 } 2732 )"; 2733 runDataflow( 2734 Code, [](llvm::ArrayRef< 2735 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2736 Results, 2737 ASTContext &ASTCtx) { 2738 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2739 const Environment &Env = Results[0].second.Env; 2740 2741 const ValueDecl *ADecl = findValueDecl(ASTCtx, "A"); 2742 ASSERT_THAT(ADecl, NotNull()); 2743 2744 const auto *AVal = 2745 dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl, SkipPast::None)); 2746 ASSERT_THAT(AVal, NotNull()); 2747 2748 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 2749 ASSERT_THAT(BDecl, NotNull()); 2750 2751 const auto *BVal = 2752 dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl, SkipPast::None)); 2753 ASSERT_THAT(BVal, NotNull()); 2754 2755 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 2756 ASSERT_THAT(CDecl, NotNull()); 2757 2758 const auto *CVal = 2759 dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 2760 ASSERT_THAT(CVal, NotNull()); 2761 2762 const ValueDecl *DDecl = findValueDecl(ASTCtx, "D"); 2763 ASSERT_THAT(DDecl, NotNull()); 2764 2765 const auto *DVal = 2766 dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl, SkipPast::None)); 2767 ASSERT_THAT(DVal, NotNull()); 2768 2769 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2770 ASSERT_THAT(FooDecl, NotNull()); 2771 2772 const auto *FooVal = dyn_cast_or_null<ConjunctionValue>( 2773 Env.getValue(*FooDecl, SkipPast::None)); 2774 ASSERT_THAT(FooVal, NotNull()); 2775 2776 const auto &FooLeftSubVal = 2777 cast<ConjunctionValue>(FooVal->getLeftSubValue()); 2778 const auto &FooLeftLeftSubVal = 2779 cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue()); 2780 EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal); 2781 EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal); 2782 EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal); 2783 EXPECT_EQ(&FooVal->getRightSubValue(), DVal); 2784 }); 2785 } 2786 } 2787 2788 TEST(TransferTest, AssignFromBoolNegation) { 2789 std::string Code = R"( 2790 void target() { 2791 bool Foo = true; 2792 bool Bar = !(Foo); 2793 // [[p]] 2794 } 2795 )"; 2796 runDataflow(Code, 2797 [](llvm::ArrayRef< 2798 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2799 Results, 2800 ASTContext &ASTCtx) { 2801 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2802 const Environment &Env = Results[0].second.Env; 2803 2804 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2805 ASSERT_THAT(FooDecl, NotNull()); 2806 2807 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2808 Env.getValue(*FooDecl, SkipPast::None)); 2809 ASSERT_THAT(FooVal, NotNull()); 2810 2811 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2812 ASSERT_THAT(BarDecl, NotNull()); 2813 2814 const auto *BarVal = dyn_cast_or_null<NegationValue>( 2815 Env.getValue(*BarDecl, SkipPast::None)); 2816 ASSERT_THAT(BarVal, NotNull()); 2817 2818 EXPECT_EQ(&BarVal->getSubVal(), FooVal); 2819 }); 2820 } 2821 2822 TEST(TransferTest, BuiltinExpect) { 2823 std::string Code = R"( 2824 void target(long Foo) { 2825 long Bar = __builtin_expect(Foo, true); 2826 /*[[p]]*/ 2827 } 2828 )"; 2829 runDataflow(Code, 2830 [](llvm::ArrayRef< 2831 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2832 Results, 2833 ASTContext &ASTCtx) { 2834 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2835 const auto &Env = Results[0].second.Env; 2836 2837 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2838 ASSERT_THAT(FooDecl, NotNull()); 2839 2840 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2841 ASSERT_THAT(BarDecl, NotNull()); 2842 2843 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2844 Env.getValue(*BarDecl, SkipPast::None)); 2845 }); 2846 } 2847 2848 // `__builtin_expect` takes and returns a `long` argument, so other types 2849 // involve casts. This verifies that we identify the input and output in that 2850 // case. 2851 TEST(TransferTest, BuiltinExpectBoolArg) { 2852 std::string Code = R"( 2853 void target(bool Foo) { 2854 bool Bar = __builtin_expect(Foo, true); 2855 /*[[p]]*/ 2856 } 2857 )"; 2858 runDataflow(Code, 2859 [](llvm::ArrayRef< 2860 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2861 Results, 2862 ASTContext &ASTCtx) { 2863 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2864 const auto &Env = Results[0].second.Env; 2865 2866 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2867 ASSERT_THAT(FooDecl, NotNull()); 2868 2869 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2870 ASSERT_THAT(BarDecl, NotNull()); 2871 2872 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2873 Env.getValue(*BarDecl, SkipPast::None)); 2874 }); 2875 } 2876 2877 TEST(TransferTest, BuiltinUnreachable) { 2878 std::string Code = R"( 2879 void target(bool Foo) { 2880 bool Bar = false; 2881 if (Foo) 2882 Bar = Foo; 2883 else 2884 __builtin_unreachable(); 2885 (void)0; 2886 /*[[p]]*/ 2887 } 2888 )"; 2889 runDataflow(Code, 2890 [](llvm::ArrayRef< 2891 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2892 Results, 2893 ASTContext &ASTCtx) { 2894 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2895 const auto &Env = Results[0].second.Env; 2896 2897 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2898 ASSERT_THAT(FooDecl, NotNull()); 2899 2900 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2901 ASSERT_THAT(BarDecl, NotNull()); 2902 2903 // `__builtin_unreachable` promises that the code is 2904 // unreachable, so the compiler treats the "then" branch as the 2905 // only possible predecessor of this statement. 2906 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2907 Env.getValue(*BarDecl, SkipPast::None)); 2908 }); 2909 } 2910 2911 TEST(TransferTest, BuiltinTrap) { 2912 std::string Code = R"( 2913 void target(bool Foo) { 2914 bool Bar = false; 2915 if (Foo) 2916 Bar = Foo; 2917 else 2918 __builtin_trap(); 2919 (void)0; 2920 /*[[p]]*/ 2921 } 2922 )"; 2923 runDataflow(Code, 2924 [](llvm::ArrayRef< 2925 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2926 Results, 2927 ASTContext &ASTCtx) { 2928 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2929 const auto &Env = Results[0].second.Env; 2930 2931 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2932 ASSERT_THAT(FooDecl, NotNull()); 2933 2934 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2935 ASSERT_THAT(BarDecl, NotNull()); 2936 2937 // `__builtin_trap` ensures program termination, so only the 2938 // "then" branch is a predecessor of this statement. 2939 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2940 Env.getValue(*BarDecl, SkipPast::None)); 2941 }); 2942 } 2943 2944 TEST(TransferTest, BuiltinDebugTrap) { 2945 std::string Code = R"( 2946 void target(bool Foo) { 2947 bool Bar = false; 2948 if (Foo) 2949 Bar = Foo; 2950 else 2951 __builtin_debugtrap(); 2952 (void)0; 2953 /*[[p]]*/ 2954 } 2955 )"; 2956 runDataflow(Code, 2957 [](llvm::ArrayRef< 2958 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2959 Results, 2960 ASTContext &ASTCtx) { 2961 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2962 const auto &Env = Results[0].second.Env; 2963 2964 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2965 ASSERT_THAT(FooDecl, NotNull()); 2966 2967 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2968 ASSERT_THAT(BarDecl, NotNull()); 2969 2970 // `__builtin_debugtrap` doesn't ensure program termination. 2971 EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None), 2972 Env.getValue(*BarDecl, SkipPast::None)); 2973 }); 2974 } 2975 2976 TEST(TransferTest, StaticIntSingleVarDecl) { 2977 std::string Code = R"( 2978 void target() { 2979 static int Foo; 2980 // [[p]] 2981 } 2982 )"; 2983 runDataflow(Code, 2984 [](llvm::ArrayRef< 2985 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2986 Results, 2987 ASTContext &ASTCtx) { 2988 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2989 const Environment &Env = Results[0].second.Env; 2990 2991 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2992 ASSERT_THAT(FooDecl, NotNull()); 2993 2994 const StorageLocation *FooLoc = 2995 Env.getStorageLocation(*FooDecl, SkipPast::None); 2996 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 2997 2998 const Value *FooVal = Env.getValue(*FooLoc); 2999 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3000 }); 3001 } 3002 3003 TEST(TransferTest, StaticIntGroupVarDecl) { 3004 std::string Code = R"( 3005 void target() { 3006 static int Foo, Bar; 3007 (void)0; 3008 // [[p]] 3009 } 3010 )"; 3011 runDataflow(Code, 3012 [](llvm::ArrayRef< 3013 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3014 Results, 3015 ASTContext &ASTCtx) { 3016 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3017 const Environment &Env = Results[0].second.Env; 3018 3019 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3020 ASSERT_THAT(FooDecl, NotNull()); 3021 3022 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3023 ASSERT_THAT(BarDecl, NotNull()); 3024 3025 const StorageLocation *FooLoc = 3026 Env.getStorageLocation(*FooDecl, SkipPast::None); 3027 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3028 3029 const StorageLocation *BarLoc = 3030 Env.getStorageLocation(*BarDecl, SkipPast::None); 3031 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 3032 3033 const Value *FooVal = Env.getValue(*FooLoc); 3034 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3035 3036 const Value *BarVal = Env.getValue(*BarLoc); 3037 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 3038 3039 EXPECT_NE(FooVal, BarVal); 3040 }); 3041 } 3042 3043 TEST(TransferTest, GlobalIntVarDecl) { 3044 std::string Code = R"( 3045 static int Foo; 3046 3047 void target() { 3048 int Bar = Foo; 3049 int Baz = Foo; 3050 // [[p]] 3051 } 3052 )"; 3053 runDataflow(Code, 3054 [](llvm::ArrayRef< 3055 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3056 Results, 3057 ASTContext &ASTCtx) { 3058 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3059 const Environment &Env = Results[0].second.Env; 3060 3061 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3062 ASSERT_THAT(BarDecl, NotNull()); 3063 3064 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3065 ASSERT_THAT(BazDecl, NotNull()); 3066 3067 const Value *BarVal = 3068 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3069 const Value *BazVal = 3070 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 3071 EXPECT_EQ(BarVal, BazVal); 3072 }); 3073 } 3074 3075 TEST(TransferTest, StaticMemberIntVarDecl) { 3076 std::string Code = R"( 3077 struct A { 3078 static int Foo; 3079 }; 3080 3081 void target(A a) { 3082 int Bar = a.Foo; 3083 int Baz = a.Foo; 3084 // [[p]] 3085 } 3086 )"; 3087 runDataflow(Code, 3088 [](llvm::ArrayRef< 3089 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3090 Results, 3091 ASTContext &ASTCtx) { 3092 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3093 const Environment &Env = Results[0].second.Env; 3094 3095 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3096 ASSERT_THAT(BarDecl, NotNull()); 3097 3098 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3099 ASSERT_THAT(BazDecl, NotNull()); 3100 3101 const Value *BarVal = 3102 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3103 const Value *BazVal = 3104 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 3105 EXPECT_EQ(BarVal, BazVal); 3106 }); 3107 } 3108 3109 TEST(TransferTest, StaticMemberRefVarDecl) { 3110 std::string Code = R"( 3111 struct A { 3112 static int &Foo; 3113 }; 3114 3115 void target(A a) { 3116 int Bar = a.Foo; 3117 int Baz = a.Foo; 3118 // [[p]] 3119 } 3120 )"; 3121 runDataflow(Code, 3122 [](llvm::ArrayRef< 3123 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3124 Results, 3125 ASTContext &ASTCtx) { 3126 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3127 const Environment &Env = Results[0].second.Env; 3128 3129 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3130 ASSERT_THAT(BarDecl, NotNull()); 3131 3132 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3133 ASSERT_THAT(BazDecl, NotNull()); 3134 3135 const Value *BarVal = 3136 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3137 const Value *BazVal = 3138 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 3139 EXPECT_EQ(BarVal, BazVal); 3140 }); 3141 } 3142 3143 TEST(TransferTest, AssignMemberBeforeCopy) { 3144 std::string Code = R"( 3145 struct A { 3146 int Foo; 3147 }; 3148 3149 void target() { 3150 A A1; 3151 A A2; 3152 int Bar; 3153 A1.Foo = Bar; 3154 A2 = A1; 3155 // [[p]] 3156 } 3157 )"; 3158 runDataflow(Code, 3159 [](llvm::ArrayRef< 3160 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3161 Results, 3162 ASTContext &ASTCtx) { 3163 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3164 const Environment &Env = Results[0].second.Env; 3165 3166 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3167 ASSERT_THAT(FooDecl, NotNull()); 3168 3169 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3170 ASSERT_THAT(BarDecl, NotNull()); 3171 3172 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); 3173 ASSERT_THAT(A1Decl, NotNull()); 3174 3175 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); 3176 ASSERT_THAT(A2Decl, NotNull()); 3177 3178 const auto *BarVal = 3179 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3180 3181 const auto *A2Val = 3182 cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None)); 3183 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal); 3184 }); 3185 } 3186 3187 TEST(TransferTest, BooleanEquality) { 3188 std::string Code = R"( 3189 void target(bool Bar) { 3190 bool Foo = true; 3191 if (Bar == Foo) { 3192 (void)0; 3193 /*[[p-then]]*/ 3194 } else { 3195 (void)0; 3196 /*[[p-else]]*/ 3197 } 3198 } 3199 )"; 3200 runDataflow( 3201 Code, [](llvm::ArrayRef< 3202 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3203 Results, 3204 ASTContext &ASTCtx) { 3205 ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _))); 3206 const Environment &EnvElse = Results[0].second.Env; 3207 const Environment &EnvThen = Results[1].second.Env; 3208 3209 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3210 ASSERT_THAT(BarDecl, NotNull()); 3211 3212 auto &BarValThen = 3213 *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None)); 3214 EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen)); 3215 3216 auto &BarValElse = 3217 *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None)); 3218 EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse)); 3219 }); 3220 } 3221 3222 TEST(TransferTest, BooleanInequality) { 3223 std::string Code = R"( 3224 void target(bool Bar) { 3225 bool Foo = true; 3226 if (Bar != Foo) { 3227 (void)0; 3228 /*[[p-then]]*/ 3229 } else { 3230 (void)0; 3231 /*[[p-else]]*/ 3232 } 3233 } 3234 )"; 3235 runDataflow( 3236 Code, [](llvm::ArrayRef< 3237 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3238 Results, 3239 ASTContext &ASTCtx) { 3240 ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _))); 3241 const Environment &EnvElse = Results[0].second.Env; 3242 const Environment &EnvThen = Results[1].second.Env; 3243 3244 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3245 ASSERT_THAT(BarDecl, NotNull()); 3246 3247 auto &BarValThen = 3248 *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None)); 3249 EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen)); 3250 3251 auto &BarValElse = 3252 *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None)); 3253 EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse)); 3254 }); 3255 } 3256 3257 TEST(TransferTest, CorrelatedBranches) { 3258 std::string Code = R"( 3259 void target(bool B, bool C) { 3260 if (B) { 3261 return; 3262 } 3263 (void)0; 3264 /*[[p0]]*/ 3265 if (C) { 3266 B = true; 3267 /*[[p1]]*/ 3268 } 3269 if (B) { 3270 (void)0; 3271 /*[[p2]]*/ 3272 } 3273 } 3274 )"; 3275 runDataflow( 3276 Code, [](llvm::ArrayRef< 3277 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3278 Results, 3279 ASTContext &ASTCtx) { 3280 ASSERT_THAT(Results, SizeIs(3)); 3281 3282 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3283 ASSERT_THAT(CDecl, NotNull()); 3284 3285 { 3286 ASSERT_THAT(Results[2], Pair("p0", _)); 3287 const Environment &Env = Results[2].second.Env; 3288 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3289 ASSERT_THAT(BDecl, NotNull()); 3290 auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None)); 3291 3292 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal))); 3293 } 3294 3295 { 3296 ASSERT_THAT(Results[1], Pair("p1", _)); 3297 const Environment &Env = Results[1].second.Env; 3298 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 3299 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3300 } 3301 3302 { 3303 ASSERT_THAT(Results[0], Pair("p2", _)); 3304 const Environment &Env = Results[0].second.Env; 3305 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 3306 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3307 } 3308 }); 3309 } 3310 3311 TEST(TransferTest, LoopWithAssignmentConverges) { 3312 std::string Code = R"( 3313 3314 bool &foo(); 3315 3316 void target() { 3317 do { 3318 bool Bar = foo(); 3319 if (Bar) break; 3320 (void)Bar; 3321 /*[[p]]*/ 3322 } while (true); 3323 } 3324 )"; 3325 // The key property that we are verifying is implicit in `runDataflow` -- 3326 // namely, that the analysis succeeds, rather than hitting the maximum number 3327 // of iterations. 3328 runDataflow( 3329 Code, [](llvm::ArrayRef< 3330 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3331 Results, 3332 ASTContext &ASTCtx) { 3333 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3334 const Environment &Env = Results[0].second.Env; 3335 3336 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3337 ASSERT_THAT(BarDecl, NotNull()); 3338 3339 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 3340 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3341 }); 3342 } 3343 3344 TEST(TransferTest, LoopWithReferenceAssignmentConverges) { 3345 std::string Code = R"( 3346 3347 bool &foo(); 3348 3349 void target() { 3350 do { 3351 bool& Bar = foo(); 3352 if (Bar) break; 3353 (void)Bar; 3354 /*[[p]]*/ 3355 } while (true); 3356 } 3357 )"; 3358 // The key property that we are verifying is implicit in `runDataflow` -- 3359 // namely, that the analysis succeeds, rather than hitting the maximum number 3360 // of iterations. 3361 runDataflow( 3362 Code, [](llvm::ArrayRef< 3363 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3364 Results, 3365 ASTContext &ASTCtx) { 3366 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3367 const Environment &Env = Results[0].second.Env; 3368 3369 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3370 ASSERT_THAT(BarDecl, NotNull()); 3371 3372 auto &BarVal = 3373 *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference)); 3374 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3375 }); 3376 } 3377 3378 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) { 3379 std::string Code = R"( 3380 struct Lookup { 3381 int x; 3382 }; 3383 3384 void target(Lookup val, bool b) { 3385 const Lookup* l = nullptr; 3386 while (b) { 3387 l = &val; 3388 /*[[p-inner]]*/ 3389 } 3390 (void)0; 3391 /*[[p-outer]]*/ 3392 } 3393 )"; 3394 // The key property that we are verifying is implicit in `runDataflow` -- 3395 // namely, that the analysis succeeds, rather than hitting the maximum number 3396 // of iterations. 3397 runDataflow( 3398 Code, [](llvm::ArrayRef< 3399 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3400 Results, 3401 ASTContext &ASTCtx) { 3402 ASSERT_THAT(Results, 3403 ElementsAre(Pair("p-outer", _), Pair("p-inner", _))); 3404 const Environment &OuterEnv = Results[0].second.Env; 3405 const Environment &InnerEnv = Results[1].second.Env; 3406 3407 const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val"); 3408 ASSERT_THAT(ValDecl, NotNull()); 3409 3410 const ValueDecl *LDecl = findValueDecl(ASTCtx, "l"); 3411 ASSERT_THAT(LDecl, NotNull()); 3412 3413 // Inner. 3414 auto *LVal = 3415 dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl, SkipPast::None)); 3416 ASSERT_THAT(LVal, NotNull()); 3417 3418 EXPECT_EQ(&LVal->getPointeeLoc(), 3419 InnerEnv.getStorageLocation(*ValDecl, SkipPast::Reference)); 3420 3421 // Outer. 3422 LVal = 3423 dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl, SkipPast::None)); 3424 ASSERT_THAT(LVal, NotNull()); 3425 3426 // The loop body may not have been executed, so we should not conclude 3427 // that `l` points to `val`. 3428 EXPECT_NE(&LVal->getPointeeLoc(), 3429 OuterEnv.getStorageLocation(*ValDecl, SkipPast::Reference)); 3430 }); 3431 } 3432 3433 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { 3434 std::string Code = R"( 3435 union Union { 3436 int A; 3437 float B; 3438 }; 3439 3440 void foo() { 3441 Union A; 3442 Union B; 3443 A = B; 3444 } 3445 )"; 3446 // This is a crash regression test when calling the transfer function on a 3447 // `CXXThisExpr` that refers to a union. 3448 runDataflow( 3449 Code, 3450 [](llvm::ArrayRef< 3451 std::pair<std::string, DataflowAnalysisState<NoopLattice>>>, 3452 ASTContext &) {}, 3453 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator="); 3454 } 3455 3456 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) { 3457 std::string Code = R"( 3458 struct A { 3459 int Foo; 3460 int Bar; 3461 }; 3462 3463 void target() { 3464 int Qux; 3465 A Baz; 3466 Baz.Foo = Qux; 3467 auto &FooRef = Baz.Foo; 3468 auto &BarRef = Baz.Bar; 3469 auto &[BoundFooRef, BoundBarRef] = Baz; 3470 // [[p]] 3471 } 3472 )"; 3473 runDataflow( 3474 Code, [](llvm::ArrayRef< 3475 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3476 Results, 3477 ASTContext &ASTCtx) { 3478 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3479 const Environment &Env = Results[0].second.Env; 3480 3481 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3482 ASSERT_THAT(FooRefDecl, NotNull()); 3483 3484 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3485 ASSERT_THAT(BarRefDecl, NotNull()); 3486 3487 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3488 ASSERT_THAT(QuxDecl, NotNull()); 3489 3490 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3491 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3492 3493 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3494 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3495 3496 const StorageLocation *FooRefLoc = 3497 Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); 3498 ASSERT_THAT(FooRefLoc, NotNull()); 3499 3500 const StorageLocation *BarRefLoc = 3501 Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); 3502 ASSERT_THAT(BarRefLoc, NotNull()); 3503 3504 const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); 3505 ASSERT_THAT(QuxVal, NotNull()); 3506 3507 const StorageLocation *BoundFooRefLoc = 3508 Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference); 3509 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3510 3511 const StorageLocation *BoundBarRefLoc = 3512 Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference); 3513 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3514 3515 EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal); 3516 }); 3517 } 3518 3519 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) { 3520 std::string Code = R"( 3521 struct A { 3522 int &Foo; 3523 int &Bar; 3524 }; 3525 3526 void target(A Baz) { 3527 int Qux; 3528 Baz.Foo = Qux; 3529 auto &FooRef = Baz.Foo; 3530 auto &BarRef = Baz.Bar; 3531 auto &[BoundFooRef, BoundBarRef] = Baz; 3532 // [[p]] 3533 } 3534 )"; 3535 runDataflow( 3536 Code, [](llvm::ArrayRef< 3537 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3538 Results, 3539 ASTContext &ASTCtx) { 3540 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3541 const Environment &Env = Results[0].second.Env; 3542 3543 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3544 ASSERT_THAT(FooRefDecl, NotNull()); 3545 3546 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3547 ASSERT_THAT(BarRefDecl, NotNull()); 3548 3549 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3550 ASSERT_THAT(QuxDecl, NotNull()); 3551 3552 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3553 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3554 3555 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3556 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3557 3558 const StorageLocation *FooRefLoc = 3559 Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); 3560 ASSERT_THAT(FooRefLoc, NotNull()); 3561 3562 const StorageLocation *BarRefLoc = 3563 Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); 3564 ASSERT_THAT(BarRefLoc, NotNull()); 3565 3566 const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); 3567 ASSERT_THAT(QuxVal, NotNull()); 3568 3569 const StorageLocation *BoundFooRefLoc = 3570 Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference); 3571 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3572 3573 const StorageLocation *BoundBarRefLoc = 3574 Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference); 3575 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3576 3577 EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal); 3578 }); 3579 } 3580 3581 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) { 3582 std::string Code = R"( 3583 struct A { 3584 int Foo; 3585 int Bar; 3586 }; 3587 3588 void target() { 3589 int Qux; 3590 A Baz; 3591 Baz.Foo = Qux; 3592 auto &FooRef = Baz.Foo; 3593 auto &BarRef = Baz.Bar; 3594 auto [BoundFoo, BoundBar] = Baz; 3595 // [[p]] 3596 } 3597 )"; 3598 runDataflow( 3599 Code, [](llvm::ArrayRef< 3600 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3601 Results, 3602 ASTContext &ASTCtx) { 3603 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3604 const Environment &Env = Results[0].second.Env; 3605 3606 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3607 ASSERT_THAT(FooRefDecl, NotNull()); 3608 3609 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3610 ASSERT_THAT(BarRefDecl, NotNull()); 3611 3612 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 3613 ASSERT_THAT(BoundFooDecl, NotNull()); 3614 3615 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 3616 ASSERT_THAT(BoundBarDecl, NotNull()); 3617 3618 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3619 ASSERT_THAT(QuxDecl, NotNull()); 3620 3621 const StorageLocation *FooRefLoc = 3622 Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); 3623 ASSERT_THAT(FooRefLoc, NotNull()); 3624 3625 const StorageLocation *BarRefLoc = 3626 Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); 3627 ASSERT_THAT(BarRefLoc, NotNull()); 3628 3629 const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); 3630 ASSERT_THAT(QuxVal, NotNull()); 3631 3632 const StorageLocation *BoundFooLoc = 3633 Env.getStorageLocation(*BoundFooDecl, SkipPast::Reference); 3634 EXPECT_NE(BoundFooLoc, FooRefLoc); 3635 3636 const StorageLocation *BoundBarLoc = 3637 Env.getStorageLocation(*BoundBarDecl, SkipPast::Reference); 3638 EXPECT_NE(BoundBarLoc, BarRefLoc); 3639 3640 EXPECT_EQ(Env.getValue(*BoundFooDecl, SkipPast::Reference), QuxVal); 3641 }); 3642 } 3643 3644 TEST(TransferTest, BinaryOperatorComma) { 3645 std::string Code = R"( 3646 void target(int Foo, int Bar) { 3647 int &Baz = (Foo, Bar); 3648 // [[p]] 3649 } 3650 )"; 3651 runDataflow(Code, 3652 [](llvm::ArrayRef< 3653 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3654 Results, 3655 ASTContext &ASTCtx) { 3656 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3657 const Environment &Env = Results[0].second.Env; 3658 3659 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3660 ASSERT_THAT(BarDecl, NotNull()); 3661 3662 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3663 ASSERT_THAT(BazDecl, NotNull()); 3664 3665 const StorageLocation *BarLoc = 3666 Env.getStorageLocation(*BarDecl, SkipPast::Reference); 3667 ASSERT_THAT(BarLoc, NotNull()); 3668 3669 const StorageLocation *BazLoc = 3670 Env.getStorageLocation(*BazDecl, SkipPast::Reference); 3671 EXPECT_EQ(BazLoc, BarLoc); 3672 }); 3673 } 3674 3675 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) { 3676 std::string Code = R"( 3677 void target(bool Foo) { 3678 if (Foo) { 3679 (void)0; 3680 // [[if_then]] 3681 } else { 3682 (void)0; 3683 // [[if_else]] 3684 } 3685 } 3686 )"; 3687 runDataflow( 3688 Code, [](llvm::ArrayRef< 3689 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3690 Results, 3691 ASTContext &ASTCtx) { 3692 ASSERT_THAT(Results, 3693 ElementsAre(Pair("if_else", _), Pair("if_then", _))); 3694 const Environment &ThenEnv = Results[1].second.Env; 3695 const Environment &ElseEnv = Results[0].second.Env; 3696 3697 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3698 ASSERT_THAT(FooDecl, NotNull()); 3699 3700 BoolValue &ThenFooVal = 3701 *cast<BoolValue>(ThenEnv.getValue(*FooDecl, SkipPast::None)); 3702 EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal)); 3703 3704 BoolValue &ElseFooVal = 3705 *cast<BoolValue>(ElseEnv.getValue(*FooDecl, SkipPast::None)); 3706 EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal))); 3707 }); 3708 } 3709 3710 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) { 3711 std::string Code = R"( 3712 void target(bool Foo) { 3713 while (Foo) { 3714 (void)0; 3715 // [[loop_body]] 3716 } 3717 (void)0; 3718 // [[after_loop]] 3719 } 3720 )"; 3721 runDataflow( 3722 Code, [](llvm::ArrayRef< 3723 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3724 Results, 3725 ASTContext &ASTCtx) { 3726 ASSERT_THAT(Results, 3727 ElementsAre(Pair("after_loop", _), Pair("loop_body", _))); 3728 const Environment &LoopBodyEnv = Results[1].second.Env; 3729 const Environment &AfterLoopEnv = Results[0].second.Env; 3730 3731 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3732 ASSERT_THAT(FooDecl, NotNull()); 3733 3734 BoolValue &LoopBodyFooVal = 3735 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 3736 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 3737 3738 BoolValue &AfterLoopFooVal = 3739 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None)); 3740 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 3741 AfterLoopEnv.makeNot(AfterLoopFooVal))); 3742 }); 3743 } 3744 3745 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) { 3746 std::string Code = R"( 3747 void target(bool Foo) { 3748 bool Bar = true; 3749 do { 3750 (void)0; 3751 // [[loop_body]] 3752 Bar = false; 3753 } while (Foo); 3754 (void)0; 3755 // [[after_loop]] 3756 } 3757 )"; 3758 runDataflow( 3759 Code, [](llvm::ArrayRef< 3760 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3761 Results, 3762 ASTContext &ASTCtx) { 3763 ASSERT_THAT(Results, 3764 ElementsAre(Pair("after_loop", _), Pair("loop_body", _))); 3765 const Environment &LoopBodyEnv = Results[1].second.Env; 3766 const Environment &AfterLoopEnv = Results[0].second.Env; 3767 3768 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3769 ASSERT_THAT(FooDecl, NotNull()); 3770 3771 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3772 ASSERT_THAT(BarDecl, NotNull()); 3773 3774 BoolValue &LoopBodyFooVal = 3775 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 3776 BoolValue &LoopBodyBarVal = 3777 *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl, SkipPast::None)); 3778 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies( 3779 LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal))); 3780 3781 BoolValue &AfterLoopFooVal = 3782 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None)); 3783 BoolValue &AfterLoopBarVal = 3784 *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl, SkipPast::None)); 3785 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 3786 AfterLoopEnv.makeNot(AfterLoopFooVal))); 3787 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 3788 AfterLoopEnv.makeNot(AfterLoopBarVal))); 3789 }); 3790 } 3791 3792 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) { 3793 std::string Code = R"( 3794 void target(bool Foo) { 3795 for (; Foo;) { 3796 (void)0; 3797 // [[loop_body]] 3798 } 3799 (void)0; 3800 // [[after_loop]] 3801 } 3802 )"; 3803 runDataflow( 3804 Code, [](llvm::ArrayRef< 3805 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3806 Results, 3807 ASTContext &ASTCtx) { 3808 ASSERT_THAT(Results, 3809 ElementsAre(Pair("after_loop", _), Pair("loop_body", _))); 3810 const Environment &LoopBodyEnv = Results[1].second.Env; 3811 const Environment &AfterLoopEnv = Results[0].second.Env; 3812 3813 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3814 ASSERT_THAT(FooDecl, NotNull()); 3815 3816 BoolValue &LoopBodyFooVal = 3817 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 3818 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 3819 3820 BoolValue &AfterLoopFooVal = 3821 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None)); 3822 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 3823 AfterLoopEnv.makeNot(AfterLoopFooVal))); 3824 }); 3825 } 3826 3827 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) { 3828 std::string Code = R"( 3829 void target(bool Foo) { 3830 for (;;) { 3831 (void)0; 3832 // [[loop_body]] 3833 } 3834 } 3835 )"; 3836 runDataflow( 3837 Code, [](llvm::ArrayRef< 3838 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3839 Results, 3840 ASTContext &ASTCtx) { 3841 ASSERT_THAT(Results, ElementsAre(Pair("loop_body", _))); 3842 const Environment &LoopBodyEnv = Results[0].second.Env; 3843 3844 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3845 ASSERT_THAT(FooDecl, NotNull()); 3846 3847 BoolValue &LoopBodyFooVal = 3848 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 3849 EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 3850 }); 3851 } 3852 3853 } // namespace 3854