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