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 std::string Code = R"( 2473 void target(bool A, bool B, bool C, bool D) { 2474 bool Foo = ((A && B) && C) && D; 2475 // [[p]] 2476 } 2477 )"; 2478 runDataflow( 2479 Code, [](llvm::ArrayRef< 2480 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2481 Results, 2482 ASTContext &ASTCtx) { 2483 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2484 const Environment &Env = Results[0].second.Env; 2485 2486 const ValueDecl *ADecl = findValueDecl(ASTCtx, "A"); 2487 ASSERT_THAT(ADecl, NotNull()); 2488 2489 const auto *AVal = 2490 dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl, SkipPast::None)); 2491 ASSERT_THAT(AVal, NotNull()); 2492 2493 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 2494 ASSERT_THAT(BDecl, NotNull()); 2495 2496 const auto *BVal = 2497 dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl, SkipPast::None)); 2498 ASSERT_THAT(BVal, NotNull()); 2499 2500 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 2501 ASSERT_THAT(CDecl, NotNull()); 2502 2503 const auto *CVal = 2504 dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 2505 ASSERT_THAT(CVal, NotNull()); 2506 2507 const ValueDecl *DDecl = findValueDecl(ASTCtx, "D"); 2508 ASSERT_THAT(DDecl, NotNull()); 2509 2510 const auto *DVal = 2511 dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl, SkipPast::None)); 2512 ASSERT_THAT(DVal, NotNull()); 2513 2514 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2515 ASSERT_THAT(FooDecl, NotNull()); 2516 2517 const auto *FooVal = dyn_cast_or_null<ConjunctionValue>( 2518 Env.getValue(*FooDecl, SkipPast::None)); 2519 ASSERT_THAT(FooVal, NotNull()); 2520 2521 const auto &FooLeftSubVal = 2522 cast<ConjunctionValue>(FooVal->getLeftSubValue()); 2523 const auto &FooLeftLeftSubVal = 2524 cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue()); 2525 EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal); 2526 EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal); 2527 EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal); 2528 EXPECT_EQ(&FooVal->getRightSubValue(), DVal); 2529 }); 2530 } 2531 } 2532 2533 TEST_F(TransferTest, AssignFromBoolNegation) { 2534 std::string Code = R"( 2535 void target() { 2536 bool Foo = true; 2537 bool Bar = !(Foo); 2538 // [[p]] 2539 } 2540 )"; 2541 runDataflow(Code, 2542 [](llvm::ArrayRef< 2543 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2544 Results, 2545 ASTContext &ASTCtx) { 2546 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2547 const Environment &Env = Results[0].second.Env; 2548 2549 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2550 ASSERT_THAT(FooDecl, NotNull()); 2551 2552 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2553 Env.getValue(*FooDecl, SkipPast::None)); 2554 ASSERT_THAT(FooVal, NotNull()); 2555 2556 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2557 ASSERT_THAT(BarDecl, NotNull()); 2558 2559 const auto *BarVal = dyn_cast_or_null<NegationValue>( 2560 Env.getValue(*BarDecl, SkipPast::None)); 2561 ASSERT_THAT(BarVal, NotNull()); 2562 2563 EXPECT_EQ(&BarVal->getSubVal(), FooVal); 2564 }); 2565 } 2566 2567 TEST_F(TransferTest, BuiltinExpect) { 2568 std::string Code = R"( 2569 void target(long Foo) { 2570 long Bar = __builtin_expect(Foo, true); 2571 /*[[p]]*/ 2572 } 2573 )"; 2574 runDataflow(Code, 2575 [](llvm::ArrayRef< 2576 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2577 Results, 2578 ASTContext &ASTCtx) { 2579 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2580 const auto &Env = Results[0].second.Env; 2581 2582 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2583 ASSERT_THAT(FooDecl, NotNull()); 2584 2585 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2586 ASSERT_THAT(BarDecl, NotNull()); 2587 2588 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2589 Env.getValue(*BarDecl, SkipPast::None)); 2590 }); 2591 } 2592 2593 // `__builtin_expect` takes and returns a `long` argument, so other types 2594 // involve casts. This verifies that we identify the input and output in that 2595 // case. 2596 TEST_F(TransferTest, BuiltinExpectBoolArg) { 2597 std::string Code = R"( 2598 void target(bool Foo) { 2599 bool Bar = __builtin_expect(Foo, true); 2600 /*[[p]]*/ 2601 } 2602 )"; 2603 runDataflow(Code, 2604 [](llvm::ArrayRef< 2605 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2606 Results, 2607 ASTContext &ASTCtx) { 2608 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2609 const auto &Env = Results[0].second.Env; 2610 2611 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2612 ASSERT_THAT(FooDecl, NotNull()); 2613 2614 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2615 ASSERT_THAT(BarDecl, NotNull()); 2616 2617 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2618 Env.getValue(*BarDecl, SkipPast::None)); 2619 }); 2620 } 2621 2622 TEST_F(TransferTest, BuiltinUnreachable) { 2623 std::string Code = R"( 2624 void target(bool Foo) { 2625 bool Bar = false; 2626 if (Foo) 2627 Bar = Foo; 2628 else 2629 __builtin_unreachable(); 2630 (void)0; 2631 /*[[p]]*/ 2632 } 2633 )"; 2634 runDataflow(Code, 2635 [](llvm::ArrayRef< 2636 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2637 Results, 2638 ASTContext &ASTCtx) { 2639 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2640 const auto &Env = Results[0].second.Env; 2641 2642 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2643 ASSERT_THAT(FooDecl, NotNull()); 2644 2645 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2646 ASSERT_THAT(BarDecl, NotNull()); 2647 2648 // `__builtin_unreachable` promises that the code is 2649 // unreachable, so the compiler treats the "then" branch as the 2650 // only possible predecessor of this statement. 2651 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2652 Env.getValue(*BarDecl, SkipPast::None)); 2653 }); 2654 } 2655 2656 TEST_F(TransferTest, BuiltinTrap) { 2657 std::string Code = R"( 2658 void target(bool Foo) { 2659 bool Bar = false; 2660 if (Foo) 2661 Bar = Foo; 2662 else 2663 __builtin_trap(); 2664 (void)0; 2665 /*[[p]]*/ 2666 } 2667 )"; 2668 runDataflow(Code, 2669 [](llvm::ArrayRef< 2670 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2671 Results, 2672 ASTContext &ASTCtx) { 2673 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2674 const auto &Env = Results[0].second.Env; 2675 2676 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2677 ASSERT_THAT(FooDecl, NotNull()); 2678 2679 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2680 ASSERT_THAT(BarDecl, NotNull()); 2681 2682 // `__builtin_trap` ensures program termination, so only the 2683 // "then" branch is a predecessor of this statement. 2684 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2685 Env.getValue(*BarDecl, SkipPast::None)); 2686 }); 2687 } 2688 2689 TEST_F(TransferTest, BuiltinDebugTrap) { 2690 std::string Code = R"( 2691 void target(bool Foo) { 2692 bool Bar = false; 2693 if (Foo) 2694 Bar = Foo; 2695 else 2696 __builtin_debugtrap(); 2697 (void)0; 2698 /*[[p]]*/ 2699 } 2700 )"; 2701 runDataflow(Code, 2702 [](llvm::ArrayRef< 2703 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2704 Results, 2705 ASTContext &ASTCtx) { 2706 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2707 const auto &Env = Results[0].second.Env; 2708 2709 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2710 ASSERT_THAT(FooDecl, NotNull()); 2711 2712 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2713 ASSERT_THAT(BarDecl, NotNull()); 2714 2715 // `__builtin_debugtrap` doesn't ensure program termination. 2716 EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None), 2717 Env.getValue(*BarDecl, SkipPast::None)); 2718 }); 2719 } 2720 2721 TEST_F(TransferTest, StaticIntSingleVarDecl) { 2722 std::string Code = R"( 2723 void target() { 2724 static int Foo; 2725 // [[p]] 2726 } 2727 )"; 2728 runDataflow(Code, 2729 [](llvm::ArrayRef< 2730 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2731 Results, 2732 ASTContext &ASTCtx) { 2733 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2734 const Environment &Env = Results[0].second.Env; 2735 2736 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2737 ASSERT_THAT(FooDecl, NotNull()); 2738 2739 const StorageLocation *FooLoc = 2740 Env.getStorageLocation(*FooDecl, SkipPast::None); 2741 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 2742 2743 const Value *FooVal = Env.getValue(*FooLoc); 2744 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 2745 }); 2746 } 2747 2748 TEST_F(TransferTest, StaticIntGroupVarDecl) { 2749 std::string Code = R"( 2750 void target() { 2751 static int Foo, Bar; 2752 (void)0; 2753 // [[p]] 2754 } 2755 )"; 2756 runDataflow(Code, 2757 [](llvm::ArrayRef< 2758 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2759 Results, 2760 ASTContext &ASTCtx) { 2761 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2762 const Environment &Env = Results[0].second.Env; 2763 2764 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2765 ASSERT_THAT(FooDecl, NotNull()); 2766 2767 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2768 ASSERT_THAT(BarDecl, NotNull()); 2769 2770 const StorageLocation *FooLoc = 2771 Env.getStorageLocation(*FooDecl, SkipPast::None); 2772 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 2773 2774 const StorageLocation *BarLoc = 2775 Env.getStorageLocation(*BarDecl, SkipPast::None); 2776 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 2777 2778 const Value *FooVal = Env.getValue(*FooLoc); 2779 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 2780 2781 const Value *BarVal = Env.getValue(*BarLoc); 2782 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 2783 2784 EXPECT_NE(FooVal, BarVal); 2785 }); 2786 } 2787 2788 TEST_F(TransferTest, GlobalIntVarDecl) { 2789 std::string Code = R"( 2790 static int Foo; 2791 2792 void target() { 2793 int Bar = Foo; 2794 int Baz = Foo; 2795 // [[p]] 2796 } 2797 )"; 2798 runDataflow(Code, 2799 [](llvm::ArrayRef< 2800 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2801 Results, 2802 ASTContext &ASTCtx) { 2803 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2804 const Environment &Env = Results[0].second.Env; 2805 2806 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2807 ASSERT_THAT(BarDecl, NotNull()); 2808 2809 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2810 ASSERT_THAT(BazDecl, NotNull()); 2811 2812 const Value *BarVal = 2813 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2814 const Value *BazVal = 2815 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2816 EXPECT_EQ(BarVal, BazVal); 2817 }); 2818 } 2819 2820 TEST_F(TransferTest, StaticMemberIntVarDecl) { 2821 std::string Code = R"( 2822 struct A { 2823 static int Foo; 2824 }; 2825 2826 void target(A a) { 2827 int Bar = a.Foo; 2828 int Baz = a.Foo; 2829 // [[p]] 2830 } 2831 )"; 2832 runDataflow(Code, 2833 [](llvm::ArrayRef< 2834 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2835 Results, 2836 ASTContext &ASTCtx) { 2837 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2838 const Environment &Env = Results[0].second.Env; 2839 2840 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2841 ASSERT_THAT(BarDecl, NotNull()); 2842 2843 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2844 ASSERT_THAT(BazDecl, NotNull()); 2845 2846 const Value *BarVal = 2847 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2848 const Value *BazVal = 2849 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2850 EXPECT_EQ(BarVal, BazVal); 2851 }); 2852 } 2853 2854 TEST_F(TransferTest, StaticMemberRefVarDecl) { 2855 std::string Code = R"( 2856 struct A { 2857 static int &Foo; 2858 }; 2859 2860 void target(A a) { 2861 int Bar = a.Foo; 2862 int Baz = a.Foo; 2863 // [[p]] 2864 } 2865 )"; 2866 runDataflow(Code, 2867 [](llvm::ArrayRef< 2868 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2869 Results, 2870 ASTContext &ASTCtx) { 2871 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2872 const Environment &Env = Results[0].second.Env; 2873 2874 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2875 ASSERT_THAT(BarDecl, NotNull()); 2876 2877 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2878 ASSERT_THAT(BazDecl, NotNull()); 2879 2880 const Value *BarVal = 2881 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2882 const Value *BazVal = 2883 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2884 EXPECT_EQ(BarVal, BazVal); 2885 }); 2886 } 2887 2888 TEST_F(TransferTest, AssignMemberBeforeCopy) { 2889 std::string Code = R"( 2890 struct A { 2891 int Foo; 2892 }; 2893 2894 void target() { 2895 A A1; 2896 A A2; 2897 int Bar; 2898 A1.Foo = Bar; 2899 A2 = A1; 2900 // [[p]] 2901 } 2902 )"; 2903 runDataflow(Code, 2904 [](llvm::ArrayRef< 2905 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2906 Results, 2907 ASTContext &ASTCtx) { 2908 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2909 const Environment &Env = Results[0].second.Env; 2910 2911 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2912 ASSERT_THAT(FooDecl, NotNull()); 2913 2914 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2915 ASSERT_THAT(BarDecl, NotNull()); 2916 2917 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); 2918 ASSERT_THAT(A1Decl, NotNull()); 2919 2920 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); 2921 ASSERT_THAT(A2Decl, NotNull()); 2922 2923 const auto *BarVal = 2924 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2925 2926 const auto *A2Val = 2927 cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None)); 2928 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal); 2929 }); 2930 } 2931 2932 TEST_F(TransferTest, BooleanEquality) { 2933 std::string Code = R"( 2934 void target(bool Bar) { 2935 bool Foo = true; 2936 if (Bar == Foo) { 2937 (void)0; 2938 /*[[p-then]]*/ 2939 } else { 2940 (void)0; 2941 /*[[p-else]]*/ 2942 } 2943 } 2944 )"; 2945 runDataflow( 2946 Code, [](llvm::ArrayRef< 2947 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2948 Results, 2949 ASTContext &ASTCtx) { 2950 ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _))); 2951 const Environment &EnvElse = Results[0].second.Env; 2952 const Environment &EnvThen = Results[1].second.Env; 2953 2954 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2955 ASSERT_THAT(BarDecl, NotNull()); 2956 2957 auto &BarValThen = 2958 *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None)); 2959 EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen)); 2960 2961 auto &BarValElse = 2962 *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None)); 2963 EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse)); 2964 }); 2965 } 2966 2967 TEST_F(TransferTest, BooleanInequality) { 2968 std::string Code = R"( 2969 void target(bool Bar) { 2970 bool Foo = true; 2971 if (Bar != Foo) { 2972 (void)0; 2973 /*[[p-then]]*/ 2974 } else { 2975 (void)0; 2976 /*[[p-else]]*/ 2977 } 2978 } 2979 )"; 2980 runDataflow( 2981 Code, [](llvm::ArrayRef< 2982 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2983 Results, 2984 ASTContext &ASTCtx) { 2985 ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _))); 2986 const Environment &EnvElse = Results[0].second.Env; 2987 const Environment &EnvThen = Results[1].second.Env; 2988 2989 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2990 ASSERT_THAT(BarDecl, NotNull()); 2991 2992 auto &BarValThen = 2993 *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None)); 2994 EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen)); 2995 2996 auto &BarValElse = 2997 *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None)); 2998 EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse)); 2999 }); 3000 } 3001 3002 TEST_F(TransferTest, CorrelatedBranches) { 3003 std::string Code = R"( 3004 void target(bool B, bool C) { 3005 if (B) { 3006 return; 3007 } 3008 (void)0; 3009 /*[[p0]]*/ 3010 if (C) { 3011 B = true; 3012 /*[[p1]]*/ 3013 } 3014 if (B) { 3015 (void)0; 3016 /*[[p2]]*/ 3017 } 3018 } 3019 )"; 3020 runDataflow( 3021 Code, [](llvm::ArrayRef< 3022 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3023 Results, 3024 ASTContext &ASTCtx) { 3025 ASSERT_THAT(Results, SizeIs(3)); 3026 3027 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3028 ASSERT_THAT(CDecl, NotNull()); 3029 3030 { 3031 ASSERT_THAT(Results[2], Pair("p0", _)); 3032 const Environment &Env = Results[2].second.Env; 3033 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3034 ASSERT_THAT(BDecl, NotNull()); 3035 auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None)); 3036 3037 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal))); 3038 } 3039 3040 { 3041 ASSERT_THAT(Results[1], Pair("p1", _)); 3042 const Environment &Env = Results[1].second.Env; 3043 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 3044 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3045 } 3046 3047 { 3048 ASSERT_THAT(Results[0], Pair("p2", _)); 3049 const Environment &Env = Results[0].second.Env; 3050 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 3051 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3052 } 3053 }); 3054 } 3055 3056 TEST_F(TransferTest, LoopWithAssignmentConverges) { 3057 std::string Code = R"( 3058 3059 bool &foo(); 3060 3061 void target() { 3062 do { 3063 bool Bar = foo(); 3064 if (Bar) break; 3065 (void)Bar; 3066 /*[[p]]*/ 3067 } while (true); 3068 } 3069 )"; 3070 // The key property that we are verifying is implicit in `runDataflow` -- 3071 // namely, that the analysis succeeds, rather than hitting the maximum number 3072 // of iterations. 3073 runDataflow( 3074 Code, [](llvm::ArrayRef< 3075 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3076 Results, 3077 ASTContext &ASTCtx) { 3078 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3079 const Environment &Env = Results[0].second.Env; 3080 3081 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3082 ASSERT_THAT(BarDecl, NotNull()); 3083 3084 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 3085 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3086 }); 3087 } 3088 3089 TEST_F(TransferTest, LoopWithReferenceAssignmentConverges) { 3090 std::string Code = R"( 3091 3092 bool &foo(); 3093 3094 void target() { 3095 do { 3096 bool& Bar = foo(); 3097 if (Bar) break; 3098 (void)Bar; 3099 /*[[p]]*/ 3100 } while (true); 3101 } 3102 )"; 3103 // The key property that we are verifying is implicit in `runDataflow` -- 3104 // namely, that the analysis succeeds, rather than hitting the maximum number 3105 // of iterations. 3106 runDataflow( 3107 Code, [](llvm::ArrayRef< 3108 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3109 Results, 3110 ASTContext &ASTCtx) { 3111 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3112 const Environment &Env = Results[0].second.Env; 3113 3114 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3115 ASSERT_THAT(BarDecl, NotNull()); 3116 3117 auto &BarVal = 3118 *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference)); 3119 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3120 }); 3121 } 3122 3123 TEST_F(TransferTest, LoopWithStructReferenceAssignmentConverges) { 3124 std::string Code = R"( 3125 struct Lookup { 3126 int x; 3127 }; 3128 3129 void target(Lookup val, bool b) { 3130 const Lookup* l = nullptr; 3131 while (b) { 3132 l = &val; 3133 /*[[p-inner]]*/ 3134 } 3135 (void)0; 3136 /*[[p-outer]]*/ 3137 } 3138 )"; 3139 // The key property that we are verifying is implicit in `runDataflow` -- 3140 // namely, that the analysis succeeds, rather than hitting the maximum number 3141 // of iterations. 3142 runDataflow( 3143 Code, [](llvm::ArrayRef< 3144 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3145 Results, 3146 ASTContext &ASTCtx) { 3147 ASSERT_THAT(Results, 3148 ElementsAre(Pair("p-outer", _), Pair("p-inner", _))); 3149 const Environment &OuterEnv = Results[0].second.Env; 3150 const Environment &InnerEnv = Results[1].second.Env; 3151 3152 const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val"); 3153 ASSERT_THAT(ValDecl, NotNull()); 3154 3155 const ValueDecl *LDecl = findValueDecl(ASTCtx, "l"); 3156 ASSERT_THAT(LDecl, NotNull()); 3157 3158 // Inner. 3159 auto *LVal = dyn_cast<IndirectionValue>( 3160 InnerEnv.getValue(*LDecl, SkipPast::None)); 3161 ASSERT_THAT(LVal, NotNull()); 3162 3163 EXPECT_EQ(&LVal->getPointeeLoc(), 3164 InnerEnv.getStorageLocation(*ValDecl, SkipPast::Reference)); 3165 3166 // Outer. 3167 LVal = dyn_cast<IndirectionValue>( 3168 OuterEnv.getValue(*LDecl, SkipPast::None)); 3169 ASSERT_THAT(LVal, NotNull()); 3170 3171 // The loop body may not have been executed, so we should not conclude 3172 // that `l` points to `val`. 3173 EXPECT_NE(&LVal->getPointeeLoc(), 3174 OuterEnv.getStorageLocation(*ValDecl, SkipPast::Reference)); 3175 }); 3176 } 3177 3178 } // namespace 3179