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 ASSERT_THAT_ERROR( 47 test::checkDataflow<NoopAnalysis>( 48 Code, "target", 49 [ApplyBuiltinTransfer](ASTContext &C, Environment &) { 50 return NoopAnalysis(C, ApplyBuiltinTransfer); 51 }, 52 [&Match]( 53 llvm::ArrayRef< 54 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 55 Results, 56 ASTContext &ASTCtx) { Match(Results, ASTCtx); }, 57 {"-fsyntax-only", "-fno-delayed-template-parsing", 58 "-std=" + 59 std::string( 60 LangStandard::getLangStandardForKind(Std).getName())}), 61 llvm::Succeeded()); 62 } 63 }; 64 65 TEST_F(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) { 66 std::string Code = R"( 67 void target() { 68 int Foo; 69 // [[p]] 70 } 71 )"; 72 runDataflow( 73 Code, 74 [](llvm::ArrayRef< 75 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 76 Results, 77 ASTContext &ASTCtx) { 78 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 79 const Environment &Env = Results[0].second.Env; 80 81 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 82 ASSERT_THAT(FooDecl, NotNull()); 83 84 EXPECT_EQ(Env.getStorageLocation(*FooDecl, SkipPast::None), nullptr); 85 }, 86 LangStandard::lang_cxx17, 87 /*ApplyBuiltinTransfer=*/false); 88 } 89 90 TEST_F(TransferTest, BoolVarDecl) { 91 std::string Code = R"( 92 void target() { 93 bool Foo; 94 // [[p]] 95 } 96 )"; 97 runDataflow(Code, 98 [](llvm::ArrayRef< 99 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 100 Results, 101 ASTContext &ASTCtx) { 102 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 103 const Environment &Env = Results[0].second.Env; 104 105 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 106 ASSERT_THAT(FooDecl, NotNull()); 107 108 const StorageLocation *FooLoc = 109 Env.getStorageLocation(*FooDecl, SkipPast::None); 110 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 111 112 const Value *FooVal = Env.getValue(*FooLoc); 113 EXPECT_TRUE(isa_and_nonnull<BoolValue>(FooVal)); 114 }); 115 } 116 117 TEST_F(TransferTest, IntVarDecl) { 118 std::string Code = R"( 119 void target() { 120 int Foo; 121 // [[p]] 122 } 123 )"; 124 runDataflow( 125 Code, [](llvm::ArrayRef< 126 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 127 Results, 128 ASTContext &ASTCtx) { 129 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 130 const Environment &Env = Results[0].second.Env; 131 132 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 133 ASSERT_THAT(FooDecl, NotNull()); 134 135 const StorageLocation *FooLoc = 136 Env.getStorageLocation(*FooDecl, SkipPast::None); 137 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 138 139 const Value *FooVal = Env.getValue(*FooLoc); 140 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 141 }); 142 } 143 144 TEST_F(TransferTest, StructVarDecl) { 145 std::string Code = R"( 146 struct A { 147 int Bar; 148 }; 149 150 void target() { 151 A Foo; 152 // [[p]] 153 } 154 )"; 155 runDataflow( 156 Code, [](llvm::ArrayRef< 157 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 158 Results, 159 ASTContext &ASTCtx) { 160 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 161 const Environment &Env = Results[0].second.Env; 162 163 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 164 ASSERT_THAT(FooDecl, NotNull()); 165 166 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 167 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 168 169 FieldDecl *BarDecl = nullptr; 170 for (FieldDecl *Field : FooFields) { 171 if (Field->getNameAsString() == "Bar") { 172 BarDecl = Field; 173 } else { 174 FAIL() << "Unexpected field: " << Field->getNameAsString(); 175 } 176 } 177 ASSERT_THAT(BarDecl, NotNull()); 178 179 const auto *FooLoc = cast<AggregateStorageLocation>( 180 Env.getStorageLocation(*FooDecl, SkipPast::None)); 181 const auto *BarLoc = 182 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 183 184 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 185 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 186 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 187 }); 188 } 189 190 TEST_F(TransferTest, StructVarDeclWithInit) { 191 std::string Code = R"( 192 struct A { 193 int Bar; 194 }; 195 196 A Gen(); 197 198 void target() { 199 A Foo = Gen(); 200 // [[p]] 201 } 202 )"; 203 runDataflow( 204 Code, [](llvm::ArrayRef< 205 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 206 Results, 207 ASTContext &ASTCtx) { 208 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 209 const Environment &Env = Results[0].second.Env; 210 211 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 212 ASSERT_THAT(FooDecl, NotNull()); 213 214 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 215 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 216 217 FieldDecl *BarDecl = nullptr; 218 for (FieldDecl *Field : FooFields) { 219 if (Field->getNameAsString() == "Bar") { 220 BarDecl = Field; 221 } else { 222 FAIL() << "Unexpected field: " << Field->getNameAsString(); 223 } 224 } 225 ASSERT_THAT(BarDecl, NotNull()); 226 227 const auto *FooLoc = cast<AggregateStorageLocation>( 228 Env.getStorageLocation(*FooDecl, SkipPast::None)); 229 const auto *BarLoc = 230 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 231 232 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 233 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 234 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 235 }); 236 } 237 238 TEST_F(TransferTest, ClassVarDecl) { 239 std::string Code = R"( 240 class A { 241 int Bar; 242 }; 243 244 void target() { 245 A Foo; 246 // [[p]] 247 } 248 )"; 249 runDataflow( 250 Code, [](llvm::ArrayRef< 251 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 252 Results, 253 ASTContext &ASTCtx) { 254 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 255 const Environment &Env = Results[0].second.Env; 256 257 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 258 ASSERT_THAT(FooDecl, NotNull()); 259 260 ASSERT_TRUE(FooDecl->getType()->isClassType()); 261 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 262 263 FieldDecl *BarDecl = nullptr; 264 for (FieldDecl *Field : FooFields) { 265 if (Field->getNameAsString() == "Bar") { 266 BarDecl = Field; 267 } else { 268 FAIL() << "Unexpected field: " << Field->getNameAsString(); 269 } 270 } 271 ASSERT_THAT(BarDecl, NotNull()); 272 273 const auto *FooLoc = cast<AggregateStorageLocation>( 274 Env.getStorageLocation(*FooDecl, SkipPast::None)); 275 const auto *BarLoc = 276 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 277 278 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 279 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 280 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 281 }); 282 } 283 284 TEST_F(TransferTest, ReferenceVarDecl) { 285 std::string Code = R"( 286 struct A {}; 287 288 A &getA(); 289 290 void target() { 291 A &Foo = getA(); 292 // [[p]] 293 } 294 )"; 295 runDataflow( 296 Code, [](llvm::ArrayRef< 297 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 298 Results, 299 ASTContext &ASTCtx) { 300 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 301 const Environment &Env = Results[0].second.Env; 302 303 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 304 ASSERT_THAT(FooDecl, NotNull()); 305 306 const StorageLocation *FooLoc = 307 Env.getStorageLocation(*FooDecl, SkipPast::None); 308 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 309 310 const ReferenceValue *FooVal = 311 cast<ReferenceValue>(Env.getValue(*FooLoc)); 312 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 313 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 314 315 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 316 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 317 }); 318 } 319 320 TEST_F(TransferTest, SelfReferentialReferenceVarDecl) { 321 std::string Code = R"( 322 struct A; 323 324 struct B {}; 325 326 struct C { 327 A &FooRef; 328 A *FooPtr; 329 B &BazRef; 330 B *BazPtr; 331 }; 332 333 struct A { 334 C &Bar; 335 }; 336 337 A &getA(); 338 339 void target() { 340 A &Foo = getA(); 341 // [[p]] 342 } 343 )"; 344 runDataflow(Code, [](llvm::ArrayRef<std::pair< 345 std::string, DataflowAnalysisState<NoopLattice>>> 346 Results, 347 ASTContext &ASTCtx) { 348 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 349 const Environment &Env = Results[0].second.Env; 350 351 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 352 ASSERT_THAT(FooDecl, NotNull()); 353 354 ASSERT_TRUE(FooDecl->getType()->isReferenceType()); 355 ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType()); 356 const auto FooFields = 357 FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields(); 358 359 FieldDecl *BarDecl = nullptr; 360 for (FieldDecl *Field : FooFields) { 361 if (Field->getNameAsString() == "Bar") { 362 BarDecl = Field; 363 } else { 364 FAIL() << "Unexpected field: " << Field->getNameAsString(); 365 } 366 } 367 ASSERT_THAT(BarDecl, NotNull()); 368 369 ASSERT_TRUE(BarDecl->getType()->isReferenceType()); 370 ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType()); 371 const auto BarFields = 372 BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields(); 373 374 FieldDecl *FooRefDecl = nullptr; 375 FieldDecl *FooPtrDecl = nullptr; 376 FieldDecl *BazRefDecl = nullptr; 377 FieldDecl *BazPtrDecl = nullptr; 378 for (FieldDecl *Field : BarFields) { 379 if (Field->getNameAsString() == "FooRef") { 380 FooRefDecl = Field; 381 } else if (Field->getNameAsString() == "FooPtr") { 382 FooPtrDecl = Field; 383 } else if (Field->getNameAsString() == "BazRef") { 384 BazRefDecl = Field; 385 } else if (Field->getNameAsString() == "BazPtr") { 386 BazPtrDecl = Field; 387 } else { 388 FAIL() << "Unexpected field: " << Field->getNameAsString(); 389 } 390 } 391 ASSERT_THAT(FooRefDecl, NotNull()); 392 ASSERT_THAT(FooPtrDecl, NotNull()); 393 ASSERT_THAT(BazRefDecl, NotNull()); 394 ASSERT_THAT(BazPtrDecl, NotNull()); 395 396 const auto *FooLoc = cast<ScalarStorageLocation>( 397 Env.getStorageLocation(*FooDecl, SkipPast::None)); 398 const auto *FooVal = cast<ReferenceValue>(Env.getValue(*FooLoc)); 399 const auto *FooPointeeVal = 400 cast<StructValue>(Env.getValue(FooVal->getPointeeLoc())); 401 402 const auto *BarVal = 403 cast<ReferenceValue>(FooPointeeVal->getChild(*BarDecl)); 404 const auto *BarPointeeVal = 405 cast<StructValue>(Env.getValue(BarVal->getPointeeLoc())); 406 407 const auto *FooRefVal = 408 cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl)); 409 const StorageLocation &FooRefPointeeLoc = FooRefVal->getPointeeLoc(); 410 EXPECT_THAT(Env.getValue(FooRefPointeeLoc), IsNull()); 411 412 const auto *FooPtrVal = 413 cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl)); 414 const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc(); 415 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull()); 416 417 const auto *BazRefVal = 418 cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl)); 419 const StorageLocation &BazRefPointeeLoc = BazRefVal->getPointeeLoc(); 420 EXPECT_THAT(Env.getValue(BazRefPointeeLoc), NotNull()); 421 422 const auto *BazPtrVal = 423 cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl)); 424 const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc(); 425 EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); 426 }); 427 } 428 429 TEST_F(TransferTest, PointerVarDecl) { 430 std::string Code = R"( 431 struct A {}; 432 433 A *getA(); 434 435 void target() { 436 A *Foo = getA(); 437 // [[p]] 438 } 439 )"; 440 runDataflow( 441 Code, [](llvm::ArrayRef< 442 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 443 Results, 444 ASTContext &ASTCtx) { 445 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 446 const Environment &Env = Results[0].second.Env; 447 448 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 449 ASSERT_THAT(FooDecl, NotNull()); 450 451 const StorageLocation *FooLoc = 452 Env.getStorageLocation(*FooDecl, SkipPast::None); 453 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 454 455 const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 456 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 457 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 458 459 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 460 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 461 }); 462 } 463 464 TEST_F(TransferTest, SelfReferentialPointerVarDecl) { 465 std::string Code = R"( 466 struct A; 467 468 struct B {}; 469 470 struct C { 471 A &FooRef; 472 A *FooPtr; 473 B &BazRef; 474 B *BazPtr; 475 }; 476 477 struct A { 478 C *Bar; 479 }; 480 481 A *getA(); 482 483 void target() { 484 A *Foo = getA(); 485 // [[p]] 486 } 487 )"; 488 runDataflow( 489 Code, [](llvm::ArrayRef< 490 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 491 Results, 492 ASTContext &ASTCtx) { 493 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 494 const Environment &Env = Results[0].second.Env; 495 496 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 497 ASSERT_THAT(FooDecl, NotNull()); 498 499 ASSERT_TRUE(FooDecl->getType()->isPointerType()); 500 ASSERT_TRUE(FooDecl->getType() 501 ->getAs<PointerType>() 502 ->getPointeeType() 503 ->isStructureType()); 504 const auto FooFields = FooDecl->getType() 505 ->getAs<PointerType>() 506 ->getPointeeType() 507 ->getAsRecordDecl() 508 ->fields(); 509 510 FieldDecl *BarDecl = nullptr; 511 for (FieldDecl *Field : FooFields) { 512 if (Field->getNameAsString() == "Bar") { 513 BarDecl = Field; 514 } else { 515 FAIL() << "Unexpected field: " << Field->getNameAsString(); 516 } 517 } 518 ASSERT_THAT(BarDecl, NotNull()); 519 520 ASSERT_TRUE(BarDecl->getType()->isPointerType()); 521 ASSERT_TRUE(BarDecl->getType() 522 ->getAs<PointerType>() 523 ->getPointeeType() 524 ->isStructureType()); 525 const auto BarFields = BarDecl->getType() 526 ->getAs<PointerType>() 527 ->getPointeeType() 528 ->getAsRecordDecl() 529 ->fields(); 530 531 FieldDecl *FooRefDecl = nullptr; 532 FieldDecl *FooPtrDecl = nullptr; 533 FieldDecl *BazRefDecl = nullptr; 534 FieldDecl *BazPtrDecl = nullptr; 535 for (FieldDecl *Field : BarFields) { 536 if (Field->getNameAsString() == "FooRef") { 537 FooRefDecl = Field; 538 } else if (Field->getNameAsString() == "FooPtr") { 539 FooPtrDecl = Field; 540 } else if (Field->getNameAsString() == "BazRef") { 541 BazRefDecl = Field; 542 } else if (Field->getNameAsString() == "BazPtr") { 543 BazPtrDecl = Field; 544 } else { 545 FAIL() << "Unexpected field: " << Field->getNameAsString(); 546 } 547 } 548 ASSERT_THAT(FooRefDecl, NotNull()); 549 ASSERT_THAT(FooPtrDecl, NotNull()); 550 ASSERT_THAT(BazRefDecl, NotNull()); 551 ASSERT_THAT(BazPtrDecl, NotNull()); 552 553 const auto *FooLoc = cast<ScalarStorageLocation>( 554 Env.getStorageLocation(*FooDecl, SkipPast::None)); 555 const auto *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 556 const auto *FooPointeeVal = 557 cast<StructValue>(Env.getValue(FooVal->getPointeeLoc())); 558 559 const auto *BarVal = 560 cast<PointerValue>(FooPointeeVal->getChild(*BarDecl)); 561 const auto *BarPointeeVal = 562 cast<StructValue>(Env.getValue(BarVal->getPointeeLoc())); 563 564 const auto *FooRefVal = 565 cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl)); 566 const StorageLocation &FooRefPointeeLoc = FooRefVal->getPointeeLoc(); 567 EXPECT_THAT(Env.getValue(FooRefPointeeLoc), IsNull()); 568 569 const auto *FooPtrVal = 570 cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl)); 571 const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc(); 572 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull()); 573 574 const auto *BazRefVal = 575 cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl)); 576 const StorageLocation &BazRefPointeeLoc = BazRefVal->getPointeeLoc(); 577 EXPECT_THAT(Env.getValue(BazRefPointeeLoc), NotNull()); 578 579 const auto *BazPtrVal = 580 cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl)); 581 const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc(); 582 EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); 583 }); 584 } 585 586 TEST_F(TransferTest, MultipleVarsDecl) { 587 std::string Code = R"( 588 void target() { 589 int Foo, Bar; 590 (void)0; 591 // [[p]] 592 } 593 )"; 594 runDataflow(Code, 595 [](llvm::ArrayRef< 596 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 597 Results, 598 ASTContext &ASTCtx) { 599 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 600 const Environment &Env = Results[0].second.Env; 601 602 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 603 ASSERT_THAT(FooDecl, NotNull()); 604 605 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 606 ASSERT_THAT(BarDecl, NotNull()); 607 608 const StorageLocation *FooLoc = 609 Env.getStorageLocation(*FooDecl, SkipPast::None); 610 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 611 612 const StorageLocation *BarLoc = 613 Env.getStorageLocation(*BarDecl, SkipPast::None); 614 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 615 616 const Value *FooVal = Env.getValue(*FooLoc); 617 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 618 619 const Value *BarVal = Env.getValue(*BarLoc); 620 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 621 }); 622 } 623 624 TEST_F(TransferTest, JoinVarDecl) { 625 std::string Code = R"( 626 void target(bool B) { 627 int Foo; 628 // [[p1]] 629 if (B) { 630 int Bar; 631 // [[p2]] 632 } else { 633 int Baz; 634 // [[p3]] 635 } 636 (void)0; 637 // [[p4]] 638 } 639 )"; 640 runDataflow(Code, [](llvm::ArrayRef<std::pair< 641 std::string, DataflowAnalysisState<NoopLattice>>> 642 Results, 643 ASTContext &ASTCtx) { 644 ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _), 645 Pair("p2", _), Pair("p1", _))); 646 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 647 ASSERT_THAT(FooDecl, NotNull()); 648 649 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 650 ASSERT_THAT(BarDecl, NotNull()); 651 652 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 653 ASSERT_THAT(BazDecl, NotNull()); 654 655 const Environment &Env1 = Results[3].second.Env; 656 const StorageLocation *FooLoc = 657 Env1.getStorageLocation(*FooDecl, SkipPast::None); 658 EXPECT_THAT(FooLoc, NotNull()); 659 EXPECT_THAT(Env1.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 660 EXPECT_THAT(Env1.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 661 662 const Environment &Env2 = Results[2].second.Env; 663 EXPECT_EQ(Env2.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 664 EXPECT_THAT(Env2.getStorageLocation(*BarDecl, SkipPast::None), NotNull()); 665 EXPECT_THAT(Env2.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 666 667 const Environment &Env3 = Results[1].second.Env; 668 EXPECT_EQ(Env3.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 669 EXPECT_THAT(Env3.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 670 EXPECT_THAT(Env3.getStorageLocation(*BazDecl, SkipPast::None), NotNull()); 671 672 const Environment &Env4 = Results[0].second.Env; 673 EXPECT_EQ(Env4.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 674 EXPECT_THAT(Env4.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 675 EXPECT_THAT(Env4.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 676 }); 677 } 678 679 TEST_F(TransferTest, BinaryOperatorAssign) { 680 std::string Code = R"( 681 void target() { 682 int Foo; 683 int Bar; 684 (Bar) = (Foo); 685 // [[p]] 686 } 687 )"; 688 runDataflow(Code, 689 [](llvm::ArrayRef< 690 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 691 Results, 692 ASTContext &ASTCtx) { 693 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 694 const Environment &Env = Results[0].second.Env; 695 696 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 697 ASSERT_THAT(FooDecl, NotNull()); 698 699 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 700 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 701 702 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 703 ASSERT_THAT(BarDecl, NotNull()); 704 705 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 706 }); 707 } 708 709 TEST_F(TransferTest, VarDeclInitAssign) { 710 std::string Code = R"( 711 void target() { 712 int Foo; 713 int Bar = Foo; 714 // [[p]] 715 } 716 )"; 717 runDataflow(Code, 718 [](llvm::ArrayRef< 719 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 720 Results, 721 ASTContext &ASTCtx) { 722 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 723 const Environment &Env = Results[0].second.Env; 724 725 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 726 ASSERT_THAT(FooDecl, NotNull()); 727 728 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 729 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 730 731 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 732 ASSERT_THAT(BarDecl, NotNull()); 733 734 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 735 }); 736 } 737 738 TEST_F(TransferTest, VarDeclInitAssignChained) { 739 std::string Code = R"( 740 void target() { 741 int Foo; 742 int Bar; 743 int Baz = (Bar = Foo); 744 // [[p]] 745 } 746 )"; 747 runDataflow(Code, 748 [](llvm::ArrayRef< 749 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 750 Results, 751 ASTContext &ASTCtx) { 752 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 753 const Environment &Env = Results[0].second.Env; 754 755 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 756 ASSERT_THAT(FooDecl, NotNull()); 757 758 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 759 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 760 761 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 762 ASSERT_THAT(BarDecl, NotNull()); 763 764 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 765 ASSERT_THAT(BazDecl, NotNull()); 766 767 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 768 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal); 769 }); 770 } 771 772 TEST_F(TransferTest, VarDeclInitAssignPtrDeref) { 773 std::string Code = R"( 774 void target() { 775 int Foo; 776 int *Bar; 777 *(Bar) = Foo; 778 int Baz = *(Bar); 779 // [[p]] 780 } 781 )"; 782 runDataflow(Code, 783 [](llvm::ArrayRef< 784 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 785 Results, 786 ASTContext &ASTCtx) { 787 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 788 const Environment &Env = Results[0].second.Env; 789 790 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 791 ASSERT_THAT(FooDecl, NotNull()); 792 793 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 794 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 795 796 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 797 ASSERT_THAT(BarDecl, NotNull()); 798 799 const auto *BarVal = 800 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 801 EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal); 802 803 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 804 ASSERT_THAT(BazDecl, NotNull()); 805 806 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal); 807 }); 808 } 809 810 TEST_F(TransferTest, AssignToAndFromReference) { 811 std::string Code = R"( 812 void target() { 813 int Foo; 814 int Bar; 815 int &Baz = Foo; 816 // [[p1]] 817 Baz = Bar; 818 int Qux = Baz; 819 int &Quux = Baz; 820 // [[p2]] 821 } 822 )"; 823 runDataflow( 824 Code, [](llvm::ArrayRef< 825 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 826 Results, 827 ASTContext &ASTCtx) { 828 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 829 const Environment &Env1 = Results[0].second.Env; 830 const Environment &Env2 = Results[1].second.Env; 831 832 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 833 ASSERT_THAT(FooDecl, NotNull()); 834 835 const Value *FooVal = Env1.getValue(*FooDecl, SkipPast::None); 836 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 837 838 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 839 ASSERT_THAT(BarDecl, NotNull()); 840 841 const Value *BarVal = Env1.getValue(*BarDecl, SkipPast::None); 842 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 843 844 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 845 ASSERT_THAT(BazDecl, NotNull()); 846 847 EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), FooVal); 848 849 EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BarVal); 850 EXPECT_EQ(Env2.getValue(*FooDecl, SkipPast::None), BarVal); 851 852 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 853 ASSERT_THAT(QuxDecl, NotNull()); 854 EXPECT_EQ(Env2.getValue(*QuxDecl, SkipPast::None), BarVal); 855 856 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 857 ASSERT_THAT(QuuxDecl, NotNull()); 858 EXPECT_EQ(Env2.getValue(*QuuxDecl, SkipPast::Reference), BarVal); 859 }); 860 } 861 862 TEST_F(TransferTest, MultipleParamDecls) { 863 std::string Code = R"( 864 void target(int Foo, int Bar) { 865 (void)0; 866 // [[p]] 867 } 868 )"; 869 runDataflow(Code, 870 [](llvm::ArrayRef< 871 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 872 Results, 873 ASTContext &ASTCtx) { 874 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 875 const Environment &Env = Results[0].second.Env; 876 877 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 878 ASSERT_THAT(FooDecl, NotNull()); 879 880 const StorageLocation *FooLoc = 881 Env.getStorageLocation(*FooDecl, SkipPast::None); 882 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 883 884 const Value *FooVal = Env.getValue(*FooLoc); 885 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 886 887 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 888 ASSERT_THAT(BarDecl, NotNull()); 889 890 const StorageLocation *BarLoc = 891 Env.getStorageLocation(*BarDecl, SkipPast::None); 892 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 893 894 const Value *BarVal = Env.getValue(*BarLoc); 895 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 896 }); 897 } 898 899 TEST_F(TransferTest, StructParamDecl) { 900 std::string Code = R"( 901 struct A { 902 int Bar; 903 }; 904 905 void target(A Foo) { 906 (void)0; 907 // [[p]] 908 } 909 )"; 910 runDataflow( 911 Code, [](llvm::ArrayRef< 912 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 913 Results, 914 ASTContext &ASTCtx) { 915 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 916 const Environment &Env = Results[0].second.Env; 917 918 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 919 ASSERT_THAT(FooDecl, NotNull()); 920 921 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 922 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 923 924 FieldDecl *BarDecl = nullptr; 925 for (FieldDecl *Field : FooFields) { 926 if (Field->getNameAsString() == "Bar") { 927 BarDecl = Field; 928 } else { 929 FAIL() << "Unexpected field: " << Field->getNameAsString(); 930 } 931 } 932 ASSERT_THAT(BarDecl, NotNull()); 933 934 const auto *FooLoc = cast<AggregateStorageLocation>( 935 Env.getStorageLocation(*FooDecl, SkipPast::None)); 936 const auto *BarLoc = 937 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 938 939 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 940 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 941 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 942 }); 943 } 944 945 TEST_F(TransferTest, ReferenceParamDecl) { 946 std::string Code = R"( 947 struct A {}; 948 949 void target(A &Foo) { 950 (void)0; 951 // [[p]] 952 } 953 )"; 954 runDataflow(Code, 955 [](llvm::ArrayRef< 956 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 957 Results, 958 ASTContext &ASTCtx) { 959 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 960 const Environment &Env = Results[0].second.Env; 961 962 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 963 ASSERT_THAT(FooDecl, NotNull()); 964 965 const StorageLocation *FooLoc = 966 Env.getStorageLocation(*FooDecl, SkipPast::None); 967 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 968 969 const ReferenceValue *FooVal = 970 dyn_cast<ReferenceValue>(Env.getValue(*FooLoc)); 971 ASSERT_THAT(FooVal, NotNull()); 972 973 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 974 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 975 976 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 977 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 978 }); 979 } 980 981 TEST_F(TransferTest, PointerParamDecl) { 982 std::string Code = R"( 983 struct A {}; 984 985 void target(A *Foo) { 986 (void)0; 987 // [[p]] 988 } 989 )"; 990 runDataflow( 991 Code, [](llvm::ArrayRef< 992 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 993 Results, 994 ASTContext &ASTCtx) { 995 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 996 const Environment &Env = Results[0].second.Env; 997 998 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 999 ASSERT_THAT(FooDecl, NotNull()); 1000 1001 const StorageLocation *FooLoc = 1002 Env.getStorageLocation(*FooDecl, SkipPast::None); 1003 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 1004 1005 const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 1006 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 1007 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 1008 1009 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 1010 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 1011 }); 1012 } 1013 1014 TEST_F(TransferTest, StructMember) { 1015 std::string Code = R"( 1016 struct A { 1017 int Bar; 1018 }; 1019 1020 void target(A Foo) { 1021 int Baz = Foo.Bar; 1022 // [[p]] 1023 } 1024 )"; 1025 runDataflow( 1026 Code, [](llvm::ArrayRef< 1027 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1028 Results, 1029 ASTContext &ASTCtx) { 1030 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1031 const Environment &Env = Results[0].second.Env; 1032 1033 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1034 ASSERT_THAT(FooDecl, NotNull()); 1035 1036 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1037 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1038 1039 FieldDecl *BarDecl = nullptr; 1040 for (FieldDecl *Field : FooFields) { 1041 if (Field->getNameAsString() == "Bar") { 1042 BarDecl = Field; 1043 } else { 1044 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1045 } 1046 } 1047 ASSERT_THAT(BarDecl, NotNull()); 1048 1049 const auto *FooLoc = cast<AggregateStorageLocation>( 1050 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1051 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1052 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1053 1054 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1055 ASSERT_THAT(BazDecl, NotNull()); 1056 1057 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal); 1058 }); 1059 } 1060 1061 TEST_F(TransferTest, DerivedBaseMemberClass) { 1062 std::string Code = R"( 1063 class A { 1064 int ADefault; 1065 protected: 1066 int AProtected; 1067 private: 1068 int APrivate; 1069 public: 1070 int APublic; 1071 }; 1072 1073 class B : public A { 1074 int BDefault; 1075 protected: 1076 int BProtected; 1077 private: 1078 int BPrivate; 1079 }; 1080 1081 void target() { 1082 B Foo; 1083 // [[p]] 1084 } 1085 )"; 1086 runDataflow( 1087 Code, [](llvm::ArrayRef< 1088 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1089 Results, 1090 ASTContext &ASTCtx) { 1091 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1092 const Environment &Env = Results[0].second.Env; 1093 1094 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1095 ASSERT_THAT(FooDecl, NotNull()); 1096 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1097 1098 // Derived-class fields. 1099 const FieldDecl *BDefaultDecl = nullptr; 1100 const FieldDecl *BProtectedDecl = nullptr; 1101 const FieldDecl *BPrivateDecl = nullptr; 1102 for (const FieldDecl *Field : 1103 FooDecl->getType()->getAsRecordDecl()->fields()) { 1104 if (Field->getNameAsString() == "BDefault") { 1105 BDefaultDecl = Field; 1106 } else if (Field->getNameAsString() == "BProtected") { 1107 BProtectedDecl = Field; 1108 } else if (Field->getNameAsString() == "BPrivate") { 1109 BPrivateDecl = Field; 1110 } else { 1111 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1112 } 1113 } 1114 ASSERT_THAT(BDefaultDecl, NotNull()); 1115 ASSERT_THAT(BProtectedDecl, NotNull()); 1116 ASSERT_THAT(BPrivateDecl, NotNull()); 1117 1118 // Base-class fields. 1119 const FieldDecl *ADefaultDecl = nullptr; 1120 const FieldDecl *APrivateDecl = nullptr; 1121 const FieldDecl *AProtectedDecl = nullptr; 1122 const FieldDecl *APublicDecl = nullptr; 1123 for (const clang::CXXBaseSpecifier &Base : 1124 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1125 QualType BaseType = Base.getType(); 1126 ASSERT_TRUE(BaseType->isRecordType()); 1127 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1128 if (Field->getNameAsString() == "ADefault") { 1129 ADefaultDecl = Field; 1130 } else if (Field->getNameAsString() == "AProtected") { 1131 AProtectedDecl = Field; 1132 } else if (Field->getNameAsString() == "APrivate") { 1133 APrivateDecl = Field; 1134 } else if (Field->getNameAsString() == "APublic") { 1135 APublicDecl = Field; 1136 } else { 1137 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1138 } 1139 } 1140 } 1141 ASSERT_THAT(ADefaultDecl, NotNull()); 1142 ASSERT_THAT(AProtectedDecl, NotNull()); 1143 ASSERT_THAT(APrivateDecl, NotNull()); 1144 ASSERT_THAT(APublicDecl, NotNull()); 1145 1146 const auto &FooLoc = *cast<AggregateStorageLocation>( 1147 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1148 const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc)); 1149 1150 // Note: we can't test presence of children in `FooLoc`, because 1151 // `getChild` requires its argument be present (or fails an assert). So, 1152 // we limit to testing presence in `FooVal` and coherence between the 1153 // two. 1154 1155 // Base-class fields. 1156 EXPECT_THAT(FooVal.getChild(*ADefaultDecl), IsNull()); 1157 EXPECT_THAT(FooVal.getChild(*APrivateDecl), IsNull()); 1158 1159 EXPECT_THAT(FooVal.getChild(*AProtectedDecl), NotNull()); 1160 EXPECT_EQ(Env.getValue(FooLoc.getChild(*APublicDecl)), 1161 FooVal.getChild(*APublicDecl)); 1162 EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull()); 1163 EXPECT_EQ(Env.getValue(FooLoc.getChild(*AProtectedDecl)), 1164 FooVal.getChild(*AProtectedDecl)); 1165 1166 // Derived-class fields. 1167 EXPECT_THAT(FooVal.getChild(*BDefaultDecl), NotNull()); 1168 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BDefaultDecl)), 1169 FooVal.getChild(*BDefaultDecl)); 1170 EXPECT_THAT(FooVal.getChild(*BProtectedDecl), NotNull()); 1171 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BProtectedDecl)), 1172 FooVal.getChild(*BProtectedDecl)); 1173 EXPECT_THAT(FooVal.getChild(*BPrivateDecl), NotNull()); 1174 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BPrivateDecl)), 1175 FooVal.getChild(*BPrivateDecl)); 1176 }); 1177 } 1178 1179 TEST_F(TransferTest, DerivedBaseMemberStructDefault) { 1180 std::string Code = R"( 1181 struct A { 1182 int Bar; 1183 }; 1184 struct B : public A { 1185 }; 1186 1187 void target() { 1188 B Foo; 1189 // [[p]] 1190 } 1191 )"; 1192 runDataflow( 1193 Code, [](llvm::ArrayRef< 1194 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1195 Results, 1196 ASTContext &ASTCtx) { 1197 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1198 const Environment &Env = Results[0].second.Env; 1199 1200 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1201 ASSERT_THAT(FooDecl, NotNull()); 1202 1203 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1204 const FieldDecl *BarDecl = nullptr; 1205 for (const clang::CXXBaseSpecifier &Base : 1206 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1207 QualType BaseType = Base.getType(); 1208 ASSERT_TRUE(BaseType->isStructureType()); 1209 1210 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1211 if (Field->getNameAsString() == "Bar") { 1212 BarDecl = Field; 1213 } else { 1214 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1215 } 1216 } 1217 } 1218 ASSERT_THAT(BarDecl, NotNull()); 1219 1220 const auto &FooLoc = *cast<AggregateStorageLocation>( 1221 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1222 const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc)); 1223 EXPECT_THAT(FooVal.getChild(*BarDecl), NotNull()); 1224 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BarDecl)), 1225 FooVal.getChild(*BarDecl)); 1226 }); 1227 } 1228 1229 TEST_F(TransferTest, ClassMember) { 1230 std::string Code = R"( 1231 class A { 1232 public: 1233 int Bar; 1234 }; 1235 1236 void target(A Foo) { 1237 int Baz = Foo.Bar; 1238 // [[p]] 1239 } 1240 )"; 1241 runDataflow( 1242 Code, [](llvm::ArrayRef< 1243 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1244 Results, 1245 ASTContext &ASTCtx) { 1246 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1247 const Environment &Env = Results[0].second.Env; 1248 1249 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1250 ASSERT_THAT(FooDecl, NotNull()); 1251 1252 ASSERT_TRUE(FooDecl->getType()->isClassType()); 1253 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1254 1255 FieldDecl *BarDecl = nullptr; 1256 for (FieldDecl *Field : FooFields) { 1257 if (Field->getNameAsString() == "Bar") { 1258 BarDecl = Field; 1259 } else { 1260 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1261 } 1262 } 1263 ASSERT_THAT(BarDecl, NotNull()); 1264 1265 const auto *FooLoc = cast<AggregateStorageLocation>( 1266 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1267 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1268 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1269 1270 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1271 ASSERT_THAT(BazDecl, NotNull()); 1272 1273 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal); 1274 }); 1275 } 1276 1277 TEST_F(TransferTest, ReferenceMember) { 1278 std::string Code = R"( 1279 struct A { 1280 int &Bar; 1281 }; 1282 1283 void target(A Foo) { 1284 int Baz = Foo.Bar; 1285 // [[p]] 1286 } 1287 )"; 1288 runDataflow( 1289 Code, [](llvm::ArrayRef< 1290 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1291 Results, 1292 ASTContext &ASTCtx) { 1293 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1294 const Environment &Env = Results[0].second.Env; 1295 1296 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1297 ASSERT_THAT(FooDecl, NotNull()); 1298 1299 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1300 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1301 1302 FieldDecl *BarDecl = nullptr; 1303 for (FieldDecl *Field : FooFields) { 1304 if (Field->getNameAsString() == "Bar") { 1305 BarDecl = Field; 1306 } else { 1307 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1308 } 1309 } 1310 ASSERT_THAT(BarDecl, NotNull()); 1311 1312 const auto *FooLoc = cast<AggregateStorageLocation>( 1313 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1314 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1315 const auto *BarVal = cast<ReferenceValue>(FooVal->getChild(*BarDecl)); 1316 const auto *BarPointeeVal = 1317 cast<IntegerValue>(Env.getValue(BarVal->getPointeeLoc())); 1318 1319 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1320 ASSERT_THAT(BazDecl, NotNull()); 1321 1322 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarPointeeVal); 1323 }); 1324 } 1325 1326 TEST_F(TransferTest, StructThisMember) { 1327 std::string Code = R"( 1328 struct A { 1329 int Bar; 1330 1331 struct B { 1332 int Baz; 1333 }; 1334 1335 B Qux; 1336 1337 void target() { 1338 int Foo = Bar; 1339 int Quux = Qux.Baz; 1340 // [[p]] 1341 } 1342 }; 1343 )"; 1344 runDataflow( 1345 Code, [](llvm::ArrayRef< 1346 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1347 Results, 1348 ASTContext &ASTCtx) { 1349 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1350 const Environment &Env = Results[0].second.Env; 1351 1352 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1353 Env.getThisPointeeStorageLocation()); 1354 ASSERT_THAT(ThisLoc, NotNull()); 1355 1356 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1357 ASSERT_THAT(BarDecl, NotNull()); 1358 1359 const auto *BarLoc = 1360 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1361 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1362 1363 const Value *BarVal = Env.getValue(*BarLoc); 1364 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1365 1366 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1367 ASSERT_THAT(FooDecl, NotNull()); 1368 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1369 1370 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1371 ASSERT_THAT(QuxDecl, NotNull()); 1372 1373 ASSERT_TRUE(QuxDecl->getType()->isStructureType()); 1374 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1375 1376 FieldDecl *BazDecl = nullptr; 1377 for (FieldDecl *Field : QuxFields) { 1378 if (Field->getNameAsString() == "Baz") { 1379 BazDecl = Field; 1380 } else { 1381 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1382 } 1383 } 1384 ASSERT_THAT(BazDecl, NotNull()); 1385 1386 const auto *QuxLoc = 1387 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1388 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1389 ASSERT_THAT(QuxVal, NotNull()); 1390 1391 const auto *BazLoc = 1392 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1393 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1394 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1395 1396 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1397 ASSERT_THAT(QuuxDecl, NotNull()); 1398 EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal); 1399 }); 1400 } 1401 1402 TEST_F(TransferTest, ClassThisMember) { 1403 std::string Code = R"( 1404 class A { 1405 int Bar; 1406 1407 class B { 1408 public: 1409 int Baz; 1410 }; 1411 1412 B Qux; 1413 1414 void target() { 1415 int Foo = Bar; 1416 int Quux = Qux.Baz; 1417 // [[p]] 1418 } 1419 }; 1420 )"; 1421 runDataflow( 1422 Code, [](llvm::ArrayRef< 1423 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1424 Results, 1425 ASTContext &ASTCtx) { 1426 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1427 const Environment &Env = Results[0].second.Env; 1428 1429 const auto *ThisLoc = 1430 cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation()); 1431 1432 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1433 ASSERT_THAT(BarDecl, NotNull()); 1434 1435 const auto *BarLoc = 1436 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1437 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1438 1439 const Value *BarVal = Env.getValue(*BarLoc); 1440 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1441 1442 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1443 ASSERT_THAT(FooDecl, NotNull()); 1444 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1445 1446 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1447 ASSERT_THAT(QuxDecl, NotNull()); 1448 1449 ASSERT_TRUE(QuxDecl->getType()->isClassType()); 1450 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1451 1452 FieldDecl *BazDecl = nullptr; 1453 for (FieldDecl *Field : QuxFields) { 1454 if (Field->getNameAsString() == "Baz") { 1455 BazDecl = Field; 1456 } else { 1457 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1458 } 1459 } 1460 ASSERT_THAT(BazDecl, NotNull()); 1461 1462 const auto *QuxLoc = 1463 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1464 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1465 ASSERT_THAT(QuxVal, NotNull()); 1466 1467 const auto *BazLoc = 1468 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1469 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1470 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1471 1472 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1473 ASSERT_THAT(QuuxDecl, NotNull()); 1474 EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal); 1475 }); 1476 } 1477 1478 TEST_F(TransferTest, ConstructorInitializer) { 1479 std::string Code = R"( 1480 struct target { 1481 int Bar; 1482 1483 target(int Foo) : Bar(Foo) { 1484 int Qux = Bar; 1485 // [[p]] 1486 } 1487 }; 1488 )"; 1489 runDataflow(Code, 1490 [](llvm::ArrayRef< 1491 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1492 Results, 1493 ASTContext &ASTCtx) { 1494 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1495 const Environment &Env = Results[0].second.Env; 1496 1497 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1498 Env.getThisPointeeStorageLocation()); 1499 ASSERT_THAT(ThisLoc, NotNull()); 1500 1501 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1502 ASSERT_THAT(FooDecl, NotNull()); 1503 1504 const auto *FooVal = 1505 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1506 1507 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1508 ASSERT_THAT(QuxDecl, NotNull()); 1509 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1510 }); 1511 } 1512 1513 TEST_F(TransferTest, DefaultInitializer) { 1514 std::string Code = R"( 1515 struct target { 1516 int Bar; 1517 int Baz = Bar; 1518 1519 target(int Foo) : Bar(Foo) { 1520 int Qux = Baz; 1521 // [[p]] 1522 } 1523 }; 1524 )"; 1525 runDataflow(Code, 1526 [](llvm::ArrayRef< 1527 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1528 Results, 1529 ASTContext &ASTCtx) { 1530 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1531 const Environment &Env = Results[0].second.Env; 1532 1533 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1534 Env.getThisPointeeStorageLocation()); 1535 ASSERT_THAT(ThisLoc, NotNull()); 1536 1537 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1538 ASSERT_THAT(FooDecl, NotNull()); 1539 1540 const auto *FooVal = 1541 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1542 1543 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1544 ASSERT_THAT(QuxDecl, NotNull()); 1545 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1546 }); 1547 } 1548 1549 TEST_F(TransferTest, DefaultInitializerReference) { 1550 std::string Code = R"( 1551 struct target { 1552 int &Bar; 1553 int &Baz = Bar; 1554 1555 target(int &Foo) : Bar(Foo) { 1556 int &Qux = Baz; 1557 // [[p]] 1558 } 1559 }; 1560 )"; 1561 runDataflow( 1562 Code, [](llvm::ArrayRef< 1563 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1564 Results, 1565 ASTContext &ASTCtx) { 1566 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1567 const Environment &Env = Results[0].second.Env; 1568 1569 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1570 Env.getThisPointeeStorageLocation()); 1571 ASSERT_THAT(ThisLoc, NotNull()); 1572 1573 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1574 ASSERT_THAT(FooDecl, NotNull()); 1575 1576 const auto *FooVal = 1577 cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None)); 1578 1579 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1580 ASSERT_THAT(QuxDecl, NotNull()); 1581 1582 const auto *QuxVal = 1583 cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None)); 1584 EXPECT_EQ(&QuxVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 1585 }); 1586 } 1587 1588 TEST_F(TransferTest, TemporaryObject) { 1589 std::string Code = R"( 1590 struct A { 1591 int Bar; 1592 }; 1593 1594 void target() { 1595 A Foo = A(); 1596 // [[p]] 1597 } 1598 )"; 1599 runDataflow( 1600 Code, [](llvm::ArrayRef< 1601 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1602 Results, 1603 ASTContext &ASTCtx) { 1604 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1605 const Environment &Env = Results[0].second.Env; 1606 1607 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1608 ASSERT_THAT(FooDecl, NotNull()); 1609 1610 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1611 ASSERT_THAT(BarDecl, NotNull()); 1612 1613 const auto *FooLoc = cast<AggregateStorageLocation>( 1614 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1615 const auto *BarLoc = 1616 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1617 1618 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1619 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1620 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1621 }); 1622 } 1623 1624 TEST_F(TransferTest, ElidableConstructor) { 1625 // This test is effectively the same as TransferTest.TemporaryObject, but 1626 // the code is compiled as C++ 14. 1627 std::string Code = R"( 1628 struct A { 1629 int Bar; 1630 }; 1631 1632 void target() { 1633 A Foo = A(); 1634 // [[p]] 1635 } 1636 )"; 1637 runDataflow( 1638 Code, 1639 [](llvm::ArrayRef< 1640 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1641 Results, 1642 ASTContext &ASTCtx) { 1643 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1644 const Environment &Env = Results[0].second.Env; 1645 1646 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1647 ASSERT_THAT(FooDecl, NotNull()); 1648 1649 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1650 ASSERT_THAT(BarDecl, NotNull()); 1651 1652 const auto *FooLoc = cast<AggregateStorageLocation>( 1653 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1654 const auto *BarLoc = 1655 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1656 1657 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1658 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1659 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1660 }, 1661 LangStandard::lang_cxx14); 1662 } 1663 1664 TEST_F(TransferTest, AssignmentOperator) { 1665 std::string Code = R"( 1666 struct A { 1667 int Baz; 1668 }; 1669 1670 void target() { 1671 A Foo; 1672 A Bar; 1673 // [[p1]] 1674 Foo = Bar; 1675 // [[p2]] 1676 } 1677 )"; 1678 runDataflow( 1679 Code, [](llvm::ArrayRef< 1680 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1681 Results, 1682 ASTContext &ASTCtx) { 1683 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 1684 const Environment &Env1 = Results[0].second.Env; 1685 const Environment &Env2 = Results[1].second.Env; 1686 1687 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1688 ASSERT_THAT(FooDecl, NotNull()); 1689 1690 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1691 ASSERT_THAT(BarDecl, NotNull()); 1692 1693 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1694 ASSERT_THAT(BazDecl, NotNull()); 1695 1696 const auto *FooLoc1 = cast<AggregateStorageLocation>( 1697 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 1698 const auto *BarLoc1 = cast<AggregateStorageLocation>( 1699 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 1700 1701 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 1702 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 1703 EXPECT_NE(FooVal1, BarVal1); 1704 1705 const auto *FooBazVal1 = 1706 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 1707 const auto *BarBazVal1 = 1708 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 1709 EXPECT_NE(FooBazVal1, BarBazVal1); 1710 1711 const auto *FooLoc2 = cast<AggregateStorageLocation>( 1712 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 1713 const auto *BarLoc2 = cast<AggregateStorageLocation>( 1714 Env2.getStorageLocation(*BarDecl, SkipPast::None)); 1715 1716 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 1717 const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2)); 1718 EXPECT_EQ(FooVal2, BarVal2); 1719 1720 const auto *FooBazVal2 = 1721 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 1722 const auto *BarBazVal2 = 1723 cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl))); 1724 EXPECT_EQ(FooBazVal2, BarBazVal2); 1725 }); 1726 } 1727 1728 TEST_F(TransferTest, CopyConstructor) { 1729 std::string Code = R"( 1730 struct A { 1731 int Baz; 1732 }; 1733 1734 void target() { 1735 A Foo; 1736 A Bar = Foo; 1737 // [[p]] 1738 } 1739 )"; 1740 runDataflow( 1741 Code, [](llvm::ArrayRef< 1742 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1743 Results, 1744 ASTContext &ASTCtx) { 1745 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1746 const Environment &Env = Results[0].second.Env; 1747 1748 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1749 ASSERT_THAT(FooDecl, NotNull()); 1750 1751 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1752 ASSERT_THAT(BarDecl, NotNull()); 1753 1754 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1755 ASSERT_THAT(BazDecl, NotNull()); 1756 1757 const auto *FooLoc = cast<AggregateStorageLocation>( 1758 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1759 const auto *BarLoc = cast<AggregateStorageLocation>( 1760 Env.getStorageLocation(*BarDecl, SkipPast::None)); 1761 1762 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1763 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 1764 EXPECT_EQ(FooVal, BarVal); 1765 1766 const auto *FooBazVal = 1767 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 1768 const auto *BarBazVal = 1769 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 1770 EXPECT_EQ(FooBazVal, BarBazVal); 1771 }); 1772 } 1773 1774 TEST_F(TransferTest, CopyConstructorWithParens) { 1775 std::string Code = R"( 1776 struct A { 1777 int Baz; 1778 }; 1779 1780 void target() { 1781 A Foo; 1782 A Bar((A(Foo))); 1783 // [[p]] 1784 } 1785 )"; 1786 runDataflow( 1787 Code, [](llvm::ArrayRef< 1788 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1789 Results, 1790 ASTContext &ASTCtx) { 1791 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1792 const Environment &Env = Results[0].second.Env; 1793 1794 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1795 ASSERT_THAT(FooDecl, NotNull()); 1796 1797 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1798 ASSERT_THAT(BarDecl, NotNull()); 1799 1800 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1801 ASSERT_THAT(BazDecl, NotNull()); 1802 1803 const auto *FooLoc = cast<AggregateStorageLocation>( 1804 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1805 const auto *BarLoc = cast<AggregateStorageLocation>( 1806 Env.getStorageLocation(*BarDecl, SkipPast::None)); 1807 1808 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1809 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 1810 EXPECT_EQ(FooVal, BarVal); 1811 1812 const auto *FooBazVal = 1813 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 1814 const auto *BarBazVal = 1815 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 1816 EXPECT_EQ(FooBazVal, BarBazVal); 1817 }); 1818 } 1819 1820 TEST_F(TransferTest, MoveConstructor) { 1821 std::string Code = R"( 1822 namespace std { 1823 1824 template <typename T> struct remove_reference { using type = T; }; 1825 template <typename T> struct remove_reference<T&> { using type = T; }; 1826 template <typename T> struct remove_reference<T&&> { using type = T; }; 1827 1828 template <typename T> 1829 using remove_reference_t = typename remove_reference<T>::type; 1830 1831 template <typename T> 1832 std::remove_reference_t<T>&& move(T&& x); 1833 1834 } // namespace std 1835 1836 struct A { 1837 int Baz; 1838 }; 1839 1840 void target() { 1841 A Foo; 1842 A Bar; 1843 // [[p1]] 1844 Foo = std::move(Bar); 1845 // [[p2]] 1846 } 1847 )"; 1848 runDataflow( 1849 Code, [](llvm::ArrayRef< 1850 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1851 Results, 1852 ASTContext &ASTCtx) { 1853 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 1854 const Environment &Env1 = Results[0].second.Env; 1855 const Environment &Env2 = Results[1].second.Env; 1856 1857 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1858 ASSERT_THAT(FooDecl, NotNull()); 1859 1860 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1861 ASSERT_THAT(BarDecl, NotNull()); 1862 1863 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1864 ASSERT_THAT(BazDecl, NotNull()); 1865 1866 const auto *FooLoc1 = cast<AggregateStorageLocation>( 1867 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 1868 const auto *BarLoc1 = cast<AggregateStorageLocation>( 1869 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 1870 1871 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 1872 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 1873 EXPECT_NE(FooVal1, BarVal1); 1874 1875 const auto *FooBazVal1 = 1876 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 1877 const auto *BarBazVal1 = 1878 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 1879 EXPECT_NE(FooBazVal1, BarBazVal1); 1880 1881 const auto *FooLoc2 = cast<AggregateStorageLocation>( 1882 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 1883 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 1884 EXPECT_EQ(FooVal2, BarVal1); 1885 1886 const auto *FooBazVal2 = 1887 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 1888 EXPECT_EQ(FooBazVal2, BarBazVal1); 1889 }); 1890 } 1891 1892 TEST_F(TransferTest, BindTemporary) { 1893 std::string Code = R"( 1894 struct A { 1895 virtual ~A() = default; 1896 1897 int Baz; 1898 }; 1899 1900 void target(A Foo) { 1901 int Bar = A(Foo).Baz; 1902 // [[p]] 1903 } 1904 )"; 1905 runDataflow(Code, 1906 [](llvm::ArrayRef< 1907 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1908 Results, 1909 ASTContext &ASTCtx) { 1910 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1911 const Environment &Env = Results[0].second.Env; 1912 1913 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1914 ASSERT_THAT(FooDecl, NotNull()); 1915 1916 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1917 ASSERT_THAT(BarDecl, NotNull()); 1918 1919 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1920 ASSERT_THAT(BazDecl, NotNull()); 1921 1922 const auto &FooVal = 1923 *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 1924 const auto *BarVal = 1925 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 1926 EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl)); 1927 }); 1928 } 1929 1930 TEST_F(TransferTest, StaticCast) { 1931 std::string Code = R"( 1932 void target(int Foo) { 1933 int Bar = static_cast<int>(Foo); 1934 // [[p]] 1935 } 1936 )"; 1937 runDataflow(Code, 1938 [](llvm::ArrayRef< 1939 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1940 Results, 1941 ASTContext &ASTCtx) { 1942 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1943 const Environment &Env = Results[0].second.Env; 1944 1945 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1946 ASSERT_THAT(FooDecl, NotNull()); 1947 1948 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1949 ASSERT_THAT(BarDecl, NotNull()); 1950 1951 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 1952 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 1953 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 1954 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 1955 EXPECT_EQ(FooVal, BarVal); 1956 }); 1957 } 1958 1959 TEST_F(TransferTest, IntegralCast) { 1960 std::string Code = R"( 1961 void target(int Foo) { 1962 long Bar = Foo; 1963 // [[p]] 1964 } 1965 )"; 1966 runDataflow(Code, 1967 [](llvm::ArrayRef< 1968 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1969 Results, 1970 ASTContext &ASTCtx) { 1971 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1972 const Environment &Env = Results[0].second.Env; 1973 1974 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1975 ASSERT_THAT(FooDecl, NotNull()); 1976 1977 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1978 ASSERT_THAT(BarDecl, NotNull()); 1979 1980 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 1981 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 1982 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 1983 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 1984 EXPECT_EQ(FooVal, BarVal); 1985 }); 1986 } 1987 1988 TEST_F(TransferTest, IntegraltoBooleanCast) { 1989 std::string Code = R"( 1990 void target(int Foo) { 1991 bool Bar = Foo; 1992 // [[p]] 1993 } 1994 )"; 1995 runDataflow(Code, 1996 [](llvm::ArrayRef< 1997 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1998 Results, 1999 ASTContext &ASTCtx) { 2000 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2001 const Environment &Env = Results[0].second.Env; 2002 2003 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2004 ASSERT_THAT(FooDecl, NotNull()); 2005 2006 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2007 ASSERT_THAT(BarDecl, NotNull()); 2008 2009 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2010 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2011 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2012 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2013 }); 2014 } 2015 2016 TEST_F(TransferTest, IntegralToBooleanCastFromBool) { 2017 std::string Code = R"( 2018 void target(bool Foo) { 2019 int Zab = Foo; 2020 bool Bar = Zab; 2021 // [[p]] 2022 } 2023 )"; 2024 runDataflow(Code, 2025 [](llvm::ArrayRef< 2026 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2027 Results, 2028 ASTContext &ASTCtx) { 2029 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2030 const Environment &Env = Results[0].second.Env; 2031 2032 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2033 ASSERT_THAT(FooDecl, NotNull()); 2034 2035 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2036 ASSERT_THAT(BarDecl, NotNull()); 2037 2038 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2039 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2040 EXPECT_TRUE(isa<BoolValue>(FooVal)); 2041 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2042 EXPECT_EQ(FooVal, BarVal); 2043 }); 2044 } 2045 2046 TEST_F(TransferTest, AddrOfValue) { 2047 std::string Code = R"( 2048 void target() { 2049 int Foo; 2050 int *Bar = &Foo; 2051 // [[p]] 2052 } 2053 )"; 2054 runDataflow(Code, 2055 [](llvm::ArrayRef< 2056 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2057 Results, 2058 ASTContext &ASTCtx) { 2059 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2060 const Environment &Env = Results[0].second.Env; 2061 2062 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2063 ASSERT_THAT(FooDecl, NotNull()); 2064 2065 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2066 ASSERT_THAT(BarDecl, NotNull()); 2067 2068 const auto *FooLoc = cast<ScalarStorageLocation>( 2069 Env.getStorageLocation(*FooDecl, SkipPast::None)); 2070 const auto *BarVal = 2071 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2072 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc); 2073 }); 2074 } 2075 2076 TEST_F(TransferTest, AddrOfReference) { 2077 std::string Code = R"( 2078 void target(int *Foo) { 2079 int *Bar = &(*Foo); 2080 // [[p]] 2081 } 2082 )"; 2083 runDataflow(Code, 2084 [](llvm::ArrayRef< 2085 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2086 Results, 2087 ASTContext &ASTCtx) { 2088 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2089 const Environment &Env = Results[0].second.Env; 2090 2091 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2092 ASSERT_THAT(FooDecl, NotNull()); 2093 2094 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2095 ASSERT_THAT(BarDecl, NotNull()); 2096 2097 const auto *FooVal = 2098 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2099 const auto *BarVal = 2100 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2101 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 2102 }); 2103 } 2104 2105 TEST_F(TransferTest, DerefDependentPtr) { 2106 std::string Code = R"( 2107 template <typename T> 2108 void target(T *Foo) { 2109 T &Bar = *Foo; 2110 /*[[p]]*/ 2111 } 2112 )"; 2113 runDataflow( 2114 Code, [](llvm::ArrayRef< 2115 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2116 Results, 2117 ASTContext &ASTCtx) { 2118 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2119 const Environment &Env = Results[0].second.Env; 2120 2121 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2122 ASSERT_THAT(FooDecl, NotNull()); 2123 2124 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2125 ASSERT_THAT(BarDecl, NotNull()); 2126 2127 const auto *FooVal = 2128 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2129 const auto *BarVal = 2130 cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None)); 2131 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 2132 }); 2133 } 2134 2135 TEST_F(TransferTest, VarDeclInitAssignConditionalOperator) { 2136 std::string Code = R"( 2137 struct A {}; 2138 2139 void target(A Foo, A Bar, bool Cond) { 2140 A Baz = Cond ? Foo : Bar; 2141 /*[[p]]*/ 2142 } 2143 )"; 2144 runDataflow( 2145 Code, [](llvm::ArrayRef< 2146 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2147 Results, 2148 ASTContext &ASTCtx) { 2149 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2150 const Environment &Env = Results[0].second.Env; 2151 2152 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2153 ASSERT_THAT(FooDecl, NotNull()); 2154 2155 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2156 ASSERT_THAT(BarDecl, NotNull()); 2157 2158 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2159 ASSERT_THAT(BazDecl, NotNull()); 2160 2161 const auto *FooVal = 2162 cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 2163 const auto *BarVal = 2164 cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None)); 2165 2166 const auto *BazVal = 2167 dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None)); 2168 ASSERT_THAT(BazVal, NotNull()); 2169 2170 EXPECT_NE(BazVal, FooVal); 2171 EXPECT_NE(BazVal, BarVal); 2172 }); 2173 } 2174 2175 TEST_F(TransferTest, VarDeclInDoWhile) { 2176 std::string Code = R"( 2177 void target(int *Foo) { 2178 do { 2179 int Bar = *Foo; 2180 } while (true); 2181 (void)0; 2182 /*[[p]]*/ 2183 } 2184 )"; 2185 runDataflow(Code, 2186 [](llvm::ArrayRef< 2187 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2188 Results, 2189 ASTContext &ASTCtx) { 2190 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2191 const Environment &Env = Results[0].second.Env; 2192 2193 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2194 ASSERT_THAT(FooDecl, NotNull()); 2195 2196 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2197 ASSERT_THAT(BarDecl, NotNull()); 2198 2199 const auto *FooVal = 2200 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2201 const auto *FooPointeeVal = 2202 cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc())); 2203 2204 const auto *BarVal = dyn_cast_or_null<IntegerValue>( 2205 Env.getValue(*BarDecl, SkipPast::None)); 2206 ASSERT_THAT(BarVal, NotNull()); 2207 2208 EXPECT_EQ(BarVal, FooPointeeVal); 2209 }); 2210 } 2211 2212 TEST_F(TransferTest, AggregateInitialization) { 2213 std::string BracesCode = R"( 2214 struct A { 2215 int Foo; 2216 }; 2217 2218 struct B { 2219 int Bar; 2220 A Baz; 2221 int Qux; 2222 }; 2223 2224 void target(int BarArg, int FooArg, int QuxArg) { 2225 B Quux{BarArg, {FooArg}, QuxArg}; 2226 /*[[p]]*/ 2227 } 2228 )"; 2229 std::string BraceEllisionCode = R"( 2230 struct A { 2231 int Foo; 2232 }; 2233 2234 struct B { 2235 int Bar; 2236 A Baz; 2237 int Qux; 2238 }; 2239 2240 void target(int BarArg, int FooArg, int QuxArg) { 2241 B Quux = {BarArg, FooArg, QuxArg}; 2242 /*[[p]]*/ 2243 } 2244 )"; 2245 for (const std::string &Code : {BracesCode, BraceEllisionCode}) { 2246 runDataflow( 2247 Code, [](llvm::ArrayRef< 2248 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2249 Results, 2250 ASTContext &ASTCtx) { 2251 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2252 const Environment &Env = Results[0].second.Env; 2253 2254 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2255 ASSERT_THAT(FooDecl, NotNull()); 2256 2257 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2258 ASSERT_THAT(BarDecl, NotNull()); 2259 2260 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2261 ASSERT_THAT(BazDecl, NotNull()); 2262 2263 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2264 ASSERT_THAT(QuxDecl, NotNull()); 2265 2266 const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg"); 2267 ASSERT_THAT(FooArgDecl, NotNull()); 2268 2269 const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg"); 2270 ASSERT_THAT(BarArgDecl, NotNull()); 2271 2272 const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg"); 2273 ASSERT_THAT(QuxArgDecl, NotNull()); 2274 2275 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 2276 ASSERT_THAT(QuuxDecl, NotNull()); 2277 2278 const auto *FooArgVal = 2279 cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None)); 2280 const auto *BarArgVal = 2281 cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None)); 2282 const auto *QuxArgVal = 2283 cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None)); 2284 2285 const auto *QuuxVal = 2286 cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None)); 2287 ASSERT_THAT(QuuxVal, NotNull()); 2288 2289 const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl)); 2290 ASSERT_THAT(BazVal, NotNull()); 2291 2292 EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal); 2293 EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal); 2294 EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal); 2295 }); 2296 } 2297 } 2298 2299 TEST_F(TransferTest, AssignToUnionMember) { 2300 std::string Code = R"( 2301 union A { 2302 int Foo; 2303 }; 2304 2305 void target(int Bar) { 2306 A Baz; 2307 Baz.Foo = Bar; 2308 // [[p]] 2309 } 2310 )"; 2311 runDataflow(Code, 2312 [](llvm::ArrayRef< 2313 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2314 Results, 2315 ASTContext &ASTCtx) { 2316 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2317 const Environment &Env = Results[0].second.Env; 2318 2319 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2320 ASSERT_THAT(BazDecl, NotNull()); 2321 ASSERT_TRUE(BazDecl->getType()->isUnionType()); 2322 2323 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>( 2324 Env.getStorageLocation(*BazDecl, SkipPast::None)); 2325 ASSERT_THAT(BazLoc, NotNull()); 2326 2327 // FIXME: Add support for union types. 2328 EXPECT_THAT(Env.getValue(*BazLoc), IsNull()); 2329 }); 2330 } 2331 2332 TEST_F(TransferTest, AssignFromBoolLiteral) { 2333 std::string Code = R"( 2334 void target() { 2335 bool Foo = true; 2336 bool Bar = false; 2337 // [[p]] 2338 } 2339 )"; 2340 runDataflow(Code, 2341 [](llvm::ArrayRef< 2342 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2343 Results, 2344 ASTContext &ASTCtx) { 2345 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2346 const Environment &Env = Results[0].second.Env; 2347 2348 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2349 ASSERT_THAT(FooDecl, NotNull()); 2350 2351 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2352 Env.getValue(*FooDecl, SkipPast::None)); 2353 ASSERT_THAT(FooVal, NotNull()); 2354 2355 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2356 ASSERT_THAT(BarDecl, NotNull()); 2357 2358 const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>( 2359 Env.getValue(*BarDecl, SkipPast::None)); 2360 ASSERT_THAT(BarVal, NotNull()); 2361 2362 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true)); 2363 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false)); 2364 }); 2365 } 2366 2367 TEST_F(TransferTest, AssignFromCompositeBoolExpression) { 2368 { 2369 std::string Code = R"( 2370 void target(bool Foo, bool Bar, bool Qux) { 2371 bool Baz = (Foo) && (Bar || Qux); 2372 // [[p]] 2373 } 2374 )"; 2375 runDataflow( 2376 Code, [](llvm::ArrayRef< 2377 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2378 Results, 2379 ASTContext &ASTCtx) { 2380 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2381 const Environment &Env = Results[0].second.Env; 2382 2383 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2384 ASSERT_THAT(FooDecl, NotNull()); 2385 2386 const auto *FooVal = dyn_cast_or_null<BoolValue>( 2387 Env.getValue(*FooDecl, SkipPast::None)); 2388 ASSERT_THAT(FooVal, NotNull()); 2389 2390 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2391 ASSERT_THAT(BarDecl, NotNull()); 2392 2393 const auto *BarVal = dyn_cast_or_null<BoolValue>( 2394 Env.getValue(*BarDecl, SkipPast::None)); 2395 ASSERT_THAT(BarVal, NotNull()); 2396 2397 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2398 ASSERT_THAT(QuxDecl, NotNull()); 2399 2400 const auto *QuxVal = dyn_cast_or_null<BoolValue>( 2401 Env.getValue(*QuxDecl, SkipPast::None)); 2402 ASSERT_THAT(QuxVal, NotNull()); 2403 2404 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2405 ASSERT_THAT(BazDecl, NotNull()); 2406 2407 const auto *BazVal = dyn_cast_or_null<ConjunctionValue>( 2408 Env.getValue(*BazDecl, SkipPast::None)); 2409 ASSERT_THAT(BazVal, NotNull()); 2410 EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal); 2411 2412 const auto *BazRightSubValVal = 2413 cast<DisjunctionValue>(&BazVal->getRightSubValue()); 2414 EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal); 2415 EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal); 2416 }); 2417 } 2418 2419 { 2420 std::string Code = R"( 2421 void target(bool Foo, bool Bar, bool Qux) { 2422 bool Baz = (Foo && Qux) || (Bar); 2423 // [[p]] 2424 } 2425 )"; 2426 runDataflow( 2427 Code, [](llvm::ArrayRef< 2428 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2429 Results, 2430 ASTContext &ASTCtx) { 2431 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2432 const Environment &Env = Results[0].second.Env; 2433 2434 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2435 ASSERT_THAT(FooDecl, NotNull()); 2436 2437 const auto *FooVal = dyn_cast_or_null<BoolValue>( 2438 Env.getValue(*FooDecl, SkipPast::None)); 2439 ASSERT_THAT(FooVal, NotNull()); 2440 2441 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2442 ASSERT_THAT(BarDecl, NotNull()); 2443 2444 const auto *BarVal = dyn_cast_or_null<BoolValue>( 2445 Env.getValue(*BarDecl, SkipPast::None)); 2446 ASSERT_THAT(BarVal, NotNull()); 2447 2448 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2449 ASSERT_THAT(QuxDecl, NotNull()); 2450 2451 const auto *QuxVal = dyn_cast_or_null<BoolValue>( 2452 Env.getValue(*QuxDecl, SkipPast::None)); 2453 ASSERT_THAT(QuxVal, NotNull()); 2454 2455 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2456 ASSERT_THAT(BazDecl, NotNull()); 2457 2458 const auto *BazVal = dyn_cast_or_null<DisjunctionValue>( 2459 Env.getValue(*BazDecl, SkipPast::None)); 2460 ASSERT_THAT(BazVal, NotNull()); 2461 2462 const auto *BazLeftSubValVal = 2463 cast<ConjunctionValue>(&BazVal->getLeftSubValue()); 2464 EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal); 2465 EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal); 2466 2467 EXPECT_EQ(&BazVal->getRightSubValue(), BarVal); 2468 }); 2469 } 2470 } 2471 2472 TEST_F(TransferTest, AssignFromBoolNegation) { 2473 std::string Code = R"( 2474 void target() { 2475 bool Foo = true; 2476 bool Bar = !(Foo); 2477 // [[p]] 2478 } 2479 )"; 2480 runDataflow(Code, 2481 [](llvm::ArrayRef< 2482 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2483 Results, 2484 ASTContext &ASTCtx) { 2485 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2486 const Environment &Env = Results[0].second.Env; 2487 2488 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2489 ASSERT_THAT(FooDecl, NotNull()); 2490 2491 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2492 Env.getValue(*FooDecl, SkipPast::None)); 2493 ASSERT_THAT(FooVal, NotNull()); 2494 2495 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2496 ASSERT_THAT(BarDecl, NotNull()); 2497 2498 const auto *BarVal = dyn_cast_or_null<NegationValue>( 2499 Env.getValue(*BarDecl, SkipPast::None)); 2500 ASSERT_THAT(BarVal, NotNull()); 2501 2502 EXPECT_EQ(&BarVal->getSubVal(), FooVal); 2503 }); 2504 } 2505 2506 TEST_F(TransferTest, BuiltinExpect) { 2507 std::string Code = R"( 2508 void target(long Foo) { 2509 long Bar = __builtin_expect(Foo, true); 2510 /*[[p]]*/ 2511 } 2512 )"; 2513 runDataflow(Code, 2514 [](llvm::ArrayRef< 2515 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2516 Results, 2517 ASTContext &ASTCtx) { 2518 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2519 const auto &Env = Results[0].second.Env; 2520 2521 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2522 ASSERT_THAT(FooDecl, NotNull()); 2523 2524 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2525 ASSERT_THAT(BarDecl, NotNull()); 2526 2527 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2528 Env.getValue(*BarDecl, SkipPast::None)); 2529 }); 2530 } 2531 2532 // `__builtin_expect` takes and returns a `long` argument, so other types 2533 // involve casts. This verifies that we identify the input and output in that 2534 // case. 2535 TEST_F(TransferTest, BuiltinExpectBoolArg) { 2536 std::string Code = R"( 2537 void target(bool Foo) { 2538 bool Bar = __builtin_expect(Foo, true); 2539 /*[[p]]*/ 2540 } 2541 )"; 2542 runDataflow(Code, 2543 [](llvm::ArrayRef< 2544 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2545 Results, 2546 ASTContext &ASTCtx) { 2547 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2548 const auto &Env = Results[0].second.Env; 2549 2550 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2551 ASSERT_THAT(FooDecl, NotNull()); 2552 2553 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2554 ASSERT_THAT(BarDecl, NotNull()); 2555 2556 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2557 Env.getValue(*BarDecl, SkipPast::None)); 2558 }); 2559 } 2560 2561 TEST_F(TransferTest, BuiltinUnreachable) { 2562 std::string Code = R"( 2563 void target(bool Foo) { 2564 bool Bar = false; 2565 if (Foo) 2566 Bar = Foo; 2567 else 2568 __builtin_unreachable(); 2569 (void)0; 2570 /*[[p]]*/ 2571 } 2572 )"; 2573 runDataflow(Code, 2574 [](llvm::ArrayRef< 2575 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2576 Results, 2577 ASTContext &ASTCtx) { 2578 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2579 const auto &Env = Results[0].second.Env; 2580 2581 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2582 ASSERT_THAT(FooDecl, NotNull()); 2583 2584 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2585 ASSERT_THAT(BarDecl, NotNull()); 2586 2587 // `__builtin_unreachable` promises that the code is 2588 // unreachable, so the compiler treats the "then" branch as the 2589 // only possible predecessor of this statement. 2590 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2591 Env.getValue(*BarDecl, SkipPast::None)); 2592 }); 2593 } 2594 2595 TEST_F(TransferTest, BuiltinTrap) { 2596 std::string Code = R"( 2597 void target(bool Foo) { 2598 bool Bar = false; 2599 if (Foo) 2600 Bar = Foo; 2601 else 2602 __builtin_trap(); 2603 (void)0; 2604 /*[[p]]*/ 2605 } 2606 )"; 2607 runDataflow(Code, 2608 [](llvm::ArrayRef< 2609 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2610 Results, 2611 ASTContext &ASTCtx) { 2612 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2613 const auto &Env = Results[0].second.Env; 2614 2615 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2616 ASSERT_THAT(FooDecl, NotNull()); 2617 2618 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2619 ASSERT_THAT(BarDecl, NotNull()); 2620 2621 // `__builtin_trap` ensures program termination, so only the 2622 // "then" branch is a predecessor of this statement. 2623 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2624 Env.getValue(*BarDecl, SkipPast::None)); 2625 }); 2626 } 2627 2628 TEST_F(TransferTest, BuiltinDebugTrap) { 2629 std::string Code = R"( 2630 void target(bool Foo) { 2631 bool Bar = false; 2632 if (Foo) 2633 Bar = Foo; 2634 else 2635 __builtin_debugtrap(); 2636 (void)0; 2637 /*[[p]]*/ 2638 } 2639 )"; 2640 runDataflow(Code, 2641 [](llvm::ArrayRef< 2642 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2643 Results, 2644 ASTContext &ASTCtx) { 2645 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2646 const auto &Env = Results[0].second.Env; 2647 2648 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2649 ASSERT_THAT(FooDecl, NotNull()); 2650 2651 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2652 ASSERT_THAT(BarDecl, NotNull()); 2653 2654 // `__builtin_debugtrap` doesn't ensure program termination. 2655 EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None), 2656 Env.getValue(*BarDecl, SkipPast::None)); 2657 }); 2658 } 2659 2660 TEST_F(TransferTest, StaticIntSingleVarDecl) { 2661 std::string Code = R"( 2662 void target() { 2663 static int Foo; 2664 // [[p]] 2665 } 2666 )"; 2667 runDataflow(Code, 2668 [](llvm::ArrayRef< 2669 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2670 Results, 2671 ASTContext &ASTCtx) { 2672 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2673 const Environment &Env = Results[0].second.Env; 2674 2675 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2676 ASSERT_THAT(FooDecl, NotNull()); 2677 2678 const StorageLocation *FooLoc = 2679 Env.getStorageLocation(*FooDecl, SkipPast::None); 2680 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 2681 2682 const Value *FooVal = Env.getValue(*FooLoc); 2683 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 2684 }); 2685 } 2686 2687 TEST_F(TransferTest, StaticIntGroupVarDecl) { 2688 std::string Code = R"( 2689 void target() { 2690 static int Foo, Bar; 2691 (void)0; 2692 // [[p]] 2693 } 2694 )"; 2695 runDataflow(Code, 2696 [](llvm::ArrayRef< 2697 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2698 Results, 2699 ASTContext &ASTCtx) { 2700 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2701 const Environment &Env = Results[0].second.Env; 2702 2703 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2704 ASSERT_THAT(FooDecl, NotNull()); 2705 2706 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2707 ASSERT_THAT(BarDecl, NotNull()); 2708 2709 const StorageLocation *FooLoc = 2710 Env.getStorageLocation(*FooDecl, SkipPast::None); 2711 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 2712 2713 const StorageLocation *BarLoc = 2714 Env.getStorageLocation(*BarDecl, SkipPast::None); 2715 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 2716 2717 const Value *FooVal = Env.getValue(*FooLoc); 2718 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 2719 2720 const Value *BarVal = Env.getValue(*BarLoc); 2721 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 2722 2723 EXPECT_NE(FooVal, BarVal); 2724 }); 2725 } 2726 2727 TEST_F(TransferTest, GlobalIntVarDecl) { 2728 std::string Code = R"( 2729 static int Foo; 2730 2731 void target() { 2732 int Bar = Foo; 2733 int Baz = Foo; 2734 // [[p]] 2735 } 2736 )"; 2737 runDataflow(Code, 2738 [](llvm::ArrayRef< 2739 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2740 Results, 2741 ASTContext &ASTCtx) { 2742 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2743 const Environment &Env = Results[0].second.Env; 2744 2745 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2746 ASSERT_THAT(BarDecl, NotNull()); 2747 2748 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2749 ASSERT_THAT(BazDecl, NotNull()); 2750 2751 const Value *BarVal = 2752 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2753 const Value *BazVal = 2754 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2755 EXPECT_EQ(BarVal, BazVal); 2756 }); 2757 } 2758 2759 TEST_F(TransferTest, StaticMemberIntVarDecl) { 2760 std::string Code = R"( 2761 struct A { 2762 static int Foo; 2763 }; 2764 2765 void target(A a) { 2766 int Bar = a.Foo; 2767 int Baz = a.Foo; 2768 // [[p]] 2769 } 2770 )"; 2771 runDataflow(Code, 2772 [](llvm::ArrayRef< 2773 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2774 Results, 2775 ASTContext &ASTCtx) { 2776 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2777 const Environment &Env = Results[0].second.Env; 2778 2779 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2780 ASSERT_THAT(BarDecl, NotNull()); 2781 2782 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2783 ASSERT_THAT(BazDecl, NotNull()); 2784 2785 const Value *BarVal = 2786 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2787 const Value *BazVal = 2788 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2789 EXPECT_EQ(BarVal, BazVal); 2790 }); 2791 } 2792 2793 TEST_F(TransferTest, StaticMemberRefVarDecl) { 2794 std::string Code = R"( 2795 struct A { 2796 static int &Foo; 2797 }; 2798 2799 void target(A a) { 2800 int Bar = a.Foo; 2801 int Baz = a.Foo; 2802 // [[p]] 2803 } 2804 )"; 2805 runDataflow(Code, 2806 [](llvm::ArrayRef< 2807 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2808 Results, 2809 ASTContext &ASTCtx) { 2810 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2811 const Environment &Env = Results[0].second.Env; 2812 2813 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2814 ASSERT_THAT(BarDecl, NotNull()); 2815 2816 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2817 ASSERT_THAT(BazDecl, NotNull()); 2818 2819 const Value *BarVal = 2820 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2821 const Value *BazVal = 2822 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2823 EXPECT_EQ(BarVal, BazVal); 2824 }); 2825 } 2826 2827 TEST_F(TransferTest, AssignMemberBeforeCopy) { 2828 std::string Code = R"( 2829 struct A { 2830 int Foo; 2831 }; 2832 2833 void target() { 2834 A A1; 2835 A A2; 2836 int Bar; 2837 A1.Foo = Bar; 2838 A2 = A1; 2839 // [[p]] 2840 } 2841 )"; 2842 runDataflow(Code, 2843 [](llvm::ArrayRef< 2844 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2845 Results, 2846 ASTContext &ASTCtx) { 2847 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2848 const Environment &Env = Results[0].second.Env; 2849 2850 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2851 ASSERT_THAT(FooDecl, NotNull()); 2852 2853 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2854 ASSERT_THAT(BarDecl, NotNull()); 2855 2856 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); 2857 ASSERT_THAT(A1Decl, NotNull()); 2858 2859 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); 2860 ASSERT_THAT(A2Decl, NotNull()); 2861 2862 const auto *BarVal = 2863 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2864 2865 const auto *A2Val = 2866 cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None)); 2867 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal); 2868 }); 2869 } 2870 2871 TEST_F(TransferTest, BooleanEquality) { 2872 std::string Code = R"( 2873 void target(bool Bar) { 2874 bool Foo = true; 2875 if (Bar == Foo) { 2876 (void)0; 2877 /*[[p-then]]*/ 2878 } else { 2879 (void)0; 2880 /*[[p-else]]*/ 2881 } 2882 } 2883 )"; 2884 runDataflow( 2885 Code, [](llvm::ArrayRef< 2886 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2887 Results, 2888 ASTContext &ASTCtx) { 2889 ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _))); 2890 const Environment &EnvElse = Results[0].second.Env; 2891 const Environment &EnvThen = Results[1].second.Env; 2892 2893 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2894 ASSERT_THAT(BarDecl, NotNull()); 2895 2896 auto &BarValThen = 2897 *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None)); 2898 EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen)); 2899 2900 auto &BarValElse = 2901 *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None)); 2902 EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse)); 2903 }); 2904 } 2905 2906 TEST_F(TransferTest, BooleanInequality) { 2907 std::string Code = R"( 2908 void target(bool Bar) { 2909 bool Foo = true; 2910 if (Bar != Foo) { 2911 (void)0; 2912 /*[[p-then]]*/ 2913 } else { 2914 (void)0; 2915 /*[[p-else]]*/ 2916 } 2917 } 2918 )"; 2919 runDataflow( 2920 Code, [](llvm::ArrayRef< 2921 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2922 Results, 2923 ASTContext &ASTCtx) { 2924 ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _))); 2925 const Environment &EnvElse = Results[0].second.Env; 2926 const Environment &EnvThen = Results[1].second.Env; 2927 2928 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2929 ASSERT_THAT(BarDecl, NotNull()); 2930 2931 auto &BarValThen = 2932 *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None)); 2933 EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen)); 2934 2935 auto &BarValElse = 2936 *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None)); 2937 EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse)); 2938 }); 2939 } 2940 2941 TEST_F(TransferTest, CorrelatedBranches) { 2942 std::string Code = R"( 2943 void target(bool B, bool C) { 2944 if (B) { 2945 return; 2946 } 2947 (void)0; 2948 /*[[p0]]*/ 2949 if (C) { 2950 B = true; 2951 /*[[p1]]*/ 2952 } 2953 if (B) { 2954 (void)0; 2955 /*[[p2]]*/ 2956 } 2957 } 2958 )"; 2959 runDataflow( 2960 Code, [](llvm::ArrayRef< 2961 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2962 Results, 2963 ASTContext &ASTCtx) { 2964 ASSERT_THAT(Results, SizeIs(3)); 2965 2966 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 2967 ASSERT_THAT(CDecl, NotNull()); 2968 2969 { 2970 ASSERT_THAT(Results[2], Pair("p0", _)); 2971 const Environment &Env = Results[2].second.Env; 2972 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 2973 ASSERT_THAT(BDecl, NotNull()); 2974 auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None)); 2975 2976 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal))); 2977 } 2978 2979 { 2980 ASSERT_THAT(Results[1], Pair("p1", _)); 2981 const Environment &Env = Results[1].second.Env; 2982 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 2983 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 2984 } 2985 2986 { 2987 ASSERT_THAT(Results[0], Pair("p2", _)); 2988 const Environment &Env = Results[0].second.Env; 2989 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 2990 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 2991 } 2992 }); 2993 } 2994 2995 TEST_F(TransferTest, LoopWithAssignmentConverges) { 2996 std::string Code = R"( 2997 2998 bool &foo(); 2999 3000 void target() { 3001 do { 3002 bool Bar = foo(); 3003 if (Bar) break; 3004 (void)Bar; 3005 /*[[p]]*/ 3006 } while (true); 3007 } 3008 )"; 3009 // The key property that we are verifying is implicit in `runDataflow` -- 3010 // namely, that the analysis succeeds, rather than hitting the maximum number 3011 // of iterations. 3012 runDataflow( 3013 Code, [](llvm::ArrayRef< 3014 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3015 Results, 3016 ASTContext &ASTCtx) { 3017 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3018 const Environment &Env = Results[0].second.Env; 3019 3020 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3021 ASSERT_THAT(BarDecl, NotNull()); 3022 3023 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 3024 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3025 }); 3026 } 3027 3028 TEST_F(TransferTest, LoopWithReferenceAssignmentConverges) { 3029 std::string Code = R"( 3030 3031 bool &foo(); 3032 3033 void target() { 3034 do { 3035 bool& Bar = foo(); 3036 if (Bar) break; 3037 (void)Bar; 3038 /*[[p]]*/ 3039 } while (true); 3040 } 3041 )"; 3042 // The key property that we are verifying is implicit in `runDataflow` -- 3043 // namely, that the analysis succeeds, rather than hitting the maximum number 3044 // of iterations. 3045 runDataflow( 3046 Code, [](llvm::ArrayRef< 3047 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3048 Results, 3049 ASTContext &ASTCtx) { 3050 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3051 const Environment &Env = Results[0].second.Env; 3052 3053 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3054 ASSERT_THAT(BarDecl, NotNull()); 3055 3056 auto &BarVal = 3057 *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference)); 3058 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3059 }); 3060 } 3061 3062 } // namespace 3063