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