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, StructThisInLambda) { 1480 std::string ThisCaptureCode = R"( 1481 struct A { 1482 void frob() { 1483 [this]() { 1484 int Foo = Bar; 1485 // [[p1]] 1486 }(); 1487 } 1488 1489 int Bar; 1490 }; 1491 )"; 1492 runDataflow( 1493 ThisCaptureCode, 1494 [](llvm::ArrayRef< 1495 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1496 Results, 1497 ASTContext &ASTCtx) { 1498 ASSERT_THAT(Results, ElementsAre(Pair("p1", _))); 1499 const Environment &Env = Results[0].second.Env; 1500 1501 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1502 Env.getThisPointeeStorageLocation()); 1503 ASSERT_THAT(ThisLoc, NotNull()); 1504 1505 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1506 ASSERT_THAT(BarDecl, NotNull()); 1507 1508 const auto *BarLoc = 1509 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1510 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1511 1512 const Value *BarVal = Env.getValue(*BarLoc); 1513 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1514 1515 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1516 ASSERT_THAT(FooDecl, NotNull()); 1517 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1518 }, 1519 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1520 1521 std::string RefCaptureDefaultCode = R"( 1522 struct A { 1523 void frob() { 1524 [&]() { 1525 int Foo = Bar; 1526 // [[p2]] 1527 }(); 1528 } 1529 1530 int Bar; 1531 }; 1532 )"; 1533 runDataflow( 1534 RefCaptureDefaultCode, 1535 [](llvm::ArrayRef< 1536 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1537 Results, 1538 ASTContext &ASTCtx) { 1539 ASSERT_THAT(Results, ElementsAre(Pair("p2", _))); 1540 const Environment &Env = Results[0].second.Env; 1541 1542 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1543 Env.getThisPointeeStorageLocation()); 1544 ASSERT_THAT(ThisLoc, NotNull()); 1545 1546 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1547 ASSERT_THAT(BarDecl, NotNull()); 1548 1549 const auto *BarLoc = 1550 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1551 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1552 1553 const Value *BarVal = Env.getValue(*BarLoc); 1554 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1555 1556 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1557 ASSERT_THAT(FooDecl, NotNull()); 1558 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1559 }, 1560 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1561 1562 std::string FreeFunctionLambdaCode = R"( 1563 void foo() { 1564 int Bar; 1565 [&]() { 1566 int Foo = Bar; 1567 // [[p3]] 1568 }(); 1569 } 1570 )"; 1571 runDataflow( 1572 FreeFunctionLambdaCode, 1573 [](llvm::ArrayRef< 1574 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1575 Results, 1576 ASTContext &ASTCtx) { 1577 ASSERT_THAT(Results, ElementsAre(Pair("p3", _))); 1578 const Environment &Env = Results[0].second.Env; 1579 1580 EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull()); 1581 }, 1582 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1583 } 1584 1585 TEST_F(TransferTest, ConstructorInitializer) { 1586 std::string Code = R"( 1587 struct target { 1588 int Bar; 1589 1590 target(int Foo) : Bar(Foo) { 1591 int Qux = Bar; 1592 // [[p]] 1593 } 1594 }; 1595 )"; 1596 runDataflow(Code, 1597 [](llvm::ArrayRef< 1598 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1599 Results, 1600 ASTContext &ASTCtx) { 1601 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1602 const Environment &Env = Results[0].second.Env; 1603 1604 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1605 Env.getThisPointeeStorageLocation()); 1606 ASSERT_THAT(ThisLoc, NotNull()); 1607 1608 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1609 ASSERT_THAT(FooDecl, NotNull()); 1610 1611 const auto *FooVal = 1612 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1613 1614 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1615 ASSERT_THAT(QuxDecl, NotNull()); 1616 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1617 }); 1618 } 1619 1620 TEST_F(TransferTest, DefaultInitializer) { 1621 std::string Code = R"( 1622 struct target { 1623 int Bar; 1624 int Baz = Bar; 1625 1626 target(int Foo) : Bar(Foo) { 1627 int Qux = Baz; 1628 // [[p]] 1629 } 1630 }; 1631 )"; 1632 runDataflow(Code, 1633 [](llvm::ArrayRef< 1634 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1635 Results, 1636 ASTContext &ASTCtx) { 1637 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1638 const Environment &Env = Results[0].second.Env; 1639 1640 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1641 Env.getThisPointeeStorageLocation()); 1642 ASSERT_THAT(ThisLoc, NotNull()); 1643 1644 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1645 ASSERT_THAT(FooDecl, NotNull()); 1646 1647 const auto *FooVal = 1648 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1649 1650 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1651 ASSERT_THAT(QuxDecl, NotNull()); 1652 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1653 }); 1654 } 1655 1656 TEST_F(TransferTest, DefaultInitializerReference) { 1657 std::string Code = R"( 1658 struct target { 1659 int &Bar; 1660 int &Baz = Bar; 1661 1662 target(int &Foo) : Bar(Foo) { 1663 int &Qux = Baz; 1664 // [[p]] 1665 } 1666 }; 1667 )"; 1668 runDataflow( 1669 Code, [](llvm::ArrayRef< 1670 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1671 Results, 1672 ASTContext &ASTCtx) { 1673 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1674 const Environment &Env = Results[0].second.Env; 1675 1676 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1677 Env.getThisPointeeStorageLocation()); 1678 ASSERT_THAT(ThisLoc, NotNull()); 1679 1680 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1681 ASSERT_THAT(FooDecl, NotNull()); 1682 1683 const auto *FooVal = 1684 cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None)); 1685 1686 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1687 ASSERT_THAT(QuxDecl, NotNull()); 1688 1689 const auto *QuxVal = 1690 cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None)); 1691 EXPECT_EQ(&QuxVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 1692 }); 1693 } 1694 1695 TEST_F(TransferTest, TemporaryObject) { 1696 std::string Code = R"( 1697 struct A { 1698 int Bar; 1699 }; 1700 1701 void target() { 1702 A Foo = A(); 1703 // [[p]] 1704 } 1705 )"; 1706 runDataflow( 1707 Code, [](llvm::ArrayRef< 1708 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1709 Results, 1710 ASTContext &ASTCtx) { 1711 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1712 const Environment &Env = Results[0].second.Env; 1713 1714 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1715 ASSERT_THAT(FooDecl, NotNull()); 1716 1717 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1718 ASSERT_THAT(BarDecl, NotNull()); 1719 1720 const auto *FooLoc = cast<AggregateStorageLocation>( 1721 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1722 const auto *BarLoc = 1723 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1724 1725 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1726 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1727 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1728 }); 1729 } 1730 1731 TEST_F(TransferTest, ElidableConstructor) { 1732 // This test is effectively the same as TransferTest.TemporaryObject, but 1733 // the code is compiled as C++ 14. 1734 std::string Code = R"( 1735 struct A { 1736 int Bar; 1737 }; 1738 1739 void target() { 1740 A Foo = A(); 1741 // [[p]] 1742 } 1743 )"; 1744 runDataflow( 1745 Code, 1746 [](llvm::ArrayRef< 1747 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1748 Results, 1749 ASTContext &ASTCtx) { 1750 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1751 const Environment &Env = Results[0].second.Env; 1752 1753 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1754 ASSERT_THAT(FooDecl, NotNull()); 1755 1756 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1757 ASSERT_THAT(BarDecl, NotNull()); 1758 1759 const auto *FooLoc = cast<AggregateStorageLocation>( 1760 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1761 const auto *BarLoc = 1762 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1763 1764 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1765 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1766 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1767 }, 1768 LangStandard::lang_cxx14); 1769 } 1770 1771 TEST_F(TransferTest, AssignmentOperator) { 1772 std::string Code = R"( 1773 struct A { 1774 int Baz; 1775 }; 1776 1777 void target() { 1778 A Foo; 1779 A Bar; 1780 // [[p1]] 1781 Foo = Bar; 1782 // [[p2]] 1783 } 1784 )"; 1785 runDataflow( 1786 Code, [](llvm::ArrayRef< 1787 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1788 Results, 1789 ASTContext &ASTCtx) { 1790 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 1791 const Environment &Env1 = Results[0].second.Env; 1792 const Environment &Env2 = Results[1].second.Env; 1793 1794 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1795 ASSERT_THAT(FooDecl, NotNull()); 1796 1797 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1798 ASSERT_THAT(BarDecl, NotNull()); 1799 1800 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1801 ASSERT_THAT(BazDecl, NotNull()); 1802 1803 const auto *FooLoc1 = cast<AggregateStorageLocation>( 1804 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 1805 const auto *BarLoc1 = cast<AggregateStorageLocation>( 1806 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 1807 1808 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 1809 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 1810 EXPECT_NE(FooVal1, BarVal1); 1811 1812 const auto *FooBazVal1 = 1813 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 1814 const auto *BarBazVal1 = 1815 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 1816 EXPECT_NE(FooBazVal1, BarBazVal1); 1817 1818 const auto *FooLoc2 = cast<AggregateStorageLocation>( 1819 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 1820 const auto *BarLoc2 = cast<AggregateStorageLocation>( 1821 Env2.getStorageLocation(*BarDecl, SkipPast::None)); 1822 1823 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 1824 const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2)); 1825 EXPECT_EQ(FooVal2, BarVal2); 1826 1827 const auto *FooBazVal2 = 1828 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 1829 const auto *BarBazVal2 = 1830 cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl))); 1831 EXPECT_EQ(FooBazVal2, BarBazVal2); 1832 }); 1833 } 1834 1835 TEST_F(TransferTest, CopyConstructor) { 1836 std::string Code = R"( 1837 struct A { 1838 int Baz; 1839 }; 1840 1841 void target() { 1842 A Foo; 1843 A Bar = Foo; 1844 // [[p]] 1845 } 1846 )"; 1847 runDataflow( 1848 Code, [](llvm::ArrayRef< 1849 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1850 Results, 1851 ASTContext &ASTCtx) { 1852 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1853 const Environment &Env = Results[0].second.Env; 1854 1855 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1856 ASSERT_THAT(FooDecl, NotNull()); 1857 1858 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1859 ASSERT_THAT(BarDecl, NotNull()); 1860 1861 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1862 ASSERT_THAT(BazDecl, NotNull()); 1863 1864 const auto *FooLoc = cast<AggregateStorageLocation>( 1865 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1866 const auto *BarLoc = cast<AggregateStorageLocation>( 1867 Env.getStorageLocation(*BarDecl, SkipPast::None)); 1868 1869 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1870 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 1871 EXPECT_EQ(FooVal, BarVal); 1872 1873 const auto *FooBazVal = 1874 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 1875 const auto *BarBazVal = 1876 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 1877 EXPECT_EQ(FooBazVal, BarBazVal); 1878 }); 1879 } 1880 1881 TEST_F(TransferTest, CopyConstructorWithParens) { 1882 std::string Code = R"( 1883 struct A { 1884 int Baz; 1885 }; 1886 1887 void target() { 1888 A Foo; 1889 A Bar((A(Foo))); 1890 // [[p]] 1891 } 1892 )"; 1893 runDataflow( 1894 Code, [](llvm::ArrayRef< 1895 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1896 Results, 1897 ASTContext &ASTCtx) { 1898 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1899 const Environment &Env = Results[0].second.Env; 1900 1901 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1902 ASSERT_THAT(FooDecl, NotNull()); 1903 1904 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1905 ASSERT_THAT(BarDecl, NotNull()); 1906 1907 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1908 ASSERT_THAT(BazDecl, NotNull()); 1909 1910 const auto *FooLoc = cast<AggregateStorageLocation>( 1911 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1912 const auto *BarLoc = cast<AggregateStorageLocation>( 1913 Env.getStorageLocation(*BarDecl, SkipPast::None)); 1914 1915 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1916 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 1917 EXPECT_EQ(FooVal, BarVal); 1918 1919 const auto *FooBazVal = 1920 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 1921 const auto *BarBazVal = 1922 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 1923 EXPECT_EQ(FooBazVal, BarBazVal); 1924 }); 1925 } 1926 1927 TEST_F(TransferTest, MoveConstructor) { 1928 std::string Code = R"( 1929 namespace std { 1930 1931 template <typename T> struct remove_reference { using type = T; }; 1932 template <typename T> struct remove_reference<T&> { using type = T; }; 1933 template <typename T> struct remove_reference<T&&> { using type = T; }; 1934 1935 template <typename T> 1936 using remove_reference_t = typename remove_reference<T>::type; 1937 1938 template <typename T> 1939 std::remove_reference_t<T>&& move(T&& x); 1940 1941 } // namespace std 1942 1943 struct A { 1944 int Baz; 1945 }; 1946 1947 void target() { 1948 A Foo; 1949 A Bar; 1950 // [[p1]] 1951 Foo = std::move(Bar); 1952 // [[p2]] 1953 } 1954 )"; 1955 runDataflow( 1956 Code, [](llvm::ArrayRef< 1957 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1958 Results, 1959 ASTContext &ASTCtx) { 1960 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 1961 const Environment &Env1 = Results[0].second.Env; 1962 const Environment &Env2 = Results[1].second.Env; 1963 1964 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1965 ASSERT_THAT(FooDecl, NotNull()); 1966 1967 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1968 ASSERT_THAT(BarDecl, NotNull()); 1969 1970 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1971 ASSERT_THAT(BazDecl, NotNull()); 1972 1973 const auto *FooLoc1 = cast<AggregateStorageLocation>( 1974 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 1975 const auto *BarLoc1 = cast<AggregateStorageLocation>( 1976 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 1977 1978 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 1979 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 1980 EXPECT_NE(FooVal1, BarVal1); 1981 1982 const auto *FooBazVal1 = 1983 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 1984 const auto *BarBazVal1 = 1985 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 1986 EXPECT_NE(FooBazVal1, BarBazVal1); 1987 1988 const auto *FooLoc2 = cast<AggregateStorageLocation>( 1989 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 1990 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 1991 EXPECT_EQ(FooVal2, BarVal1); 1992 1993 const auto *FooBazVal2 = 1994 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 1995 EXPECT_EQ(FooBazVal2, BarBazVal1); 1996 }); 1997 } 1998 1999 TEST_F(TransferTest, BindTemporary) { 2000 std::string Code = R"( 2001 struct A { 2002 virtual ~A() = default; 2003 2004 int Baz; 2005 }; 2006 2007 void target(A Foo) { 2008 int Bar = A(Foo).Baz; 2009 // [[p]] 2010 } 2011 )"; 2012 runDataflow(Code, 2013 [](llvm::ArrayRef< 2014 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2015 Results, 2016 ASTContext &ASTCtx) { 2017 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2018 const Environment &Env = Results[0].second.Env; 2019 2020 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2021 ASSERT_THAT(FooDecl, NotNull()); 2022 2023 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2024 ASSERT_THAT(BarDecl, NotNull()); 2025 2026 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2027 ASSERT_THAT(BazDecl, NotNull()); 2028 2029 const auto &FooVal = 2030 *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 2031 const auto *BarVal = 2032 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2033 EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl)); 2034 }); 2035 } 2036 2037 TEST_F(TransferTest, StaticCast) { 2038 std::string Code = R"( 2039 void target(int Foo) { 2040 int Bar = static_cast<int>(Foo); 2041 // [[p]] 2042 } 2043 )"; 2044 runDataflow(Code, 2045 [](llvm::ArrayRef< 2046 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2047 Results, 2048 ASTContext &ASTCtx) { 2049 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2050 const Environment &Env = Results[0].second.Env; 2051 2052 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2053 ASSERT_THAT(FooDecl, NotNull()); 2054 2055 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2056 ASSERT_THAT(BarDecl, NotNull()); 2057 2058 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2059 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2060 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2061 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2062 EXPECT_EQ(FooVal, BarVal); 2063 }); 2064 } 2065 2066 TEST_F(TransferTest, IntegralCast) { 2067 std::string Code = R"( 2068 void target(int Foo) { 2069 long Bar = Foo; 2070 // [[p]] 2071 } 2072 )"; 2073 runDataflow(Code, 2074 [](llvm::ArrayRef< 2075 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2076 Results, 2077 ASTContext &ASTCtx) { 2078 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2079 const Environment &Env = Results[0].second.Env; 2080 2081 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2082 ASSERT_THAT(FooDecl, NotNull()); 2083 2084 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2085 ASSERT_THAT(BarDecl, NotNull()); 2086 2087 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2088 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2089 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2090 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2091 EXPECT_EQ(FooVal, BarVal); 2092 }); 2093 } 2094 2095 TEST_F(TransferTest, IntegraltoBooleanCast) { 2096 std::string Code = R"( 2097 void target(int Foo) { 2098 bool Bar = Foo; 2099 // [[p]] 2100 } 2101 )"; 2102 runDataflow(Code, 2103 [](llvm::ArrayRef< 2104 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2105 Results, 2106 ASTContext &ASTCtx) { 2107 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2108 const Environment &Env = Results[0].second.Env; 2109 2110 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2111 ASSERT_THAT(FooDecl, NotNull()); 2112 2113 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2114 ASSERT_THAT(BarDecl, NotNull()); 2115 2116 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2117 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2118 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2119 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2120 }); 2121 } 2122 2123 TEST_F(TransferTest, IntegralToBooleanCastFromBool) { 2124 std::string Code = R"( 2125 void target(bool Foo) { 2126 int Zab = Foo; 2127 bool Bar = Zab; 2128 // [[p]] 2129 } 2130 )"; 2131 runDataflow(Code, 2132 [](llvm::ArrayRef< 2133 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2134 Results, 2135 ASTContext &ASTCtx) { 2136 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2137 const Environment &Env = Results[0].second.Env; 2138 2139 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2140 ASSERT_THAT(FooDecl, NotNull()); 2141 2142 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2143 ASSERT_THAT(BarDecl, NotNull()); 2144 2145 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2146 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2147 EXPECT_TRUE(isa<BoolValue>(FooVal)); 2148 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2149 EXPECT_EQ(FooVal, BarVal); 2150 }); 2151 } 2152 2153 TEST_F(TransferTest, AddrOfValue) { 2154 std::string Code = R"( 2155 void target() { 2156 int Foo; 2157 int *Bar = &Foo; 2158 // [[p]] 2159 } 2160 )"; 2161 runDataflow(Code, 2162 [](llvm::ArrayRef< 2163 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2164 Results, 2165 ASTContext &ASTCtx) { 2166 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2167 const Environment &Env = Results[0].second.Env; 2168 2169 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2170 ASSERT_THAT(FooDecl, NotNull()); 2171 2172 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2173 ASSERT_THAT(BarDecl, NotNull()); 2174 2175 const auto *FooLoc = cast<ScalarStorageLocation>( 2176 Env.getStorageLocation(*FooDecl, SkipPast::None)); 2177 const auto *BarVal = 2178 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2179 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc); 2180 }); 2181 } 2182 2183 TEST_F(TransferTest, AddrOfReference) { 2184 std::string Code = R"( 2185 void target(int *Foo) { 2186 int *Bar = &(*Foo); 2187 // [[p]] 2188 } 2189 )"; 2190 runDataflow(Code, 2191 [](llvm::ArrayRef< 2192 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2193 Results, 2194 ASTContext &ASTCtx) { 2195 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2196 const Environment &Env = Results[0].second.Env; 2197 2198 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2199 ASSERT_THAT(FooDecl, NotNull()); 2200 2201 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2202 ASSERT_THAT(BarDecl, NotNull()); 2203 2204 const auto *FooVal = 2205 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2206 const auto *BarVal = 2207 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2208 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 2209 }); 2210 } 2211 2212 TEST_F(TransferTest, DerefDependentPtr) { 2213 std::string Code = R"( 2214 template <typename T> 2215 void target(T *Foo) { 2216 T &Bar = *Foo; 2217 /*[[p]]*/ 2218 } 2219 )"; 2220 runDataflow( 2221 Code, [](llvm::ArrayRef< 2222 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2223 Results, 2224 ASTContext &ASTCtx) { 2225 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2226 const Environment &Env = Results[0].second.Env; 2227 2228 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2229 ASSERT_THAT(FooDecl, NotNull()); 2230 2231 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2232 ASSERT_THAT(BarDecl, NotNull()); 2233 2234 const auto *FooVal = 2235 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2236 const auto *BarVal = 2237 cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None)); 2238 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 2239 }); 2240 } 2241 2242 TEST_F(TransferTest, VarDeclInitAssignConditionalOperator) { 2243 std::string Code = R"( 2244 struct A {}; 2245 2246 void target(A Foo, A Bar, bool Cond) { 2247 A Baz = Cond ? Foo : Bar; 2248 /*[[p]]*/ 2249 } 2250 )"; 2251 runDataflow( 2252 Code, [](llvm::ArrayRef< 2253 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2254 Results, 2255 ASTContext &ASTCtx) { 2256 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2257 const Environment &Env = Results[0].second.Env; 2258 2259 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2260 ASSERT_THAT(FooDecl, NotNull()); 2261 2262 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2263 ASSERT_THAT(BarDecl, NotNull()); 2264 2265 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2266 ASSERT_THAT(BazDecl, NotNull()); 2267 2268 const auto *FooVal = 2269 cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 2270 const auto *BarVal = 2271 cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None)); 2272 2273 const auto *BazVal = 2274 dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None)); 2275 ASSERT_THAT(BazVal, NotNull()); 2276 2277 EXPECT_NE(BazVal, FooVal); 2278 EXPECT_NE(BazVal, BarVal); 2279 }); 2280 } 2281 2282 TEST_F(TransferTest, VarDeclInDoWhile) { 2283 std::string Code = R"( 2284 void target(int *Foo) { 2285 do { 2286 int Bar = *Foo; 2287 } while (true); 2288 (void)0; 2289 /*[[p]]*/ 2290 } 2291 )"; 2292 runDataflow(Code, 2293 [](llvm::ArrayRef< 2294 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2295 Results, 2296 ASTContext &ASTCtx) { 2297 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2298 const Environment &Env = Results[0].second.Env; 2299 2300 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2301 ASSERT_THAT(FooDecl, NotNull()); 2302 2303 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2304 ASSERT_THAT(BarDecl, NotNull()); 2305 2306 const auto *FooVal = 2307 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2308 const auto *FooPointeeVal = 2309 cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc())); 2310 2311 const auto *BarVal = dyn_cast_or_null<IntegerValue>( 2312 Env.getValue(*BarDecl, SkipPast::None)); 2313 ASSERT_THAT(BarVal, NotNull()); 2314 2315 EXPECT_EQ(BarVal, FooPointeeVal); 2316 }); 2317 } 2318 2319 TEST_F(TransferTest, AggregateInitialization) { 2320 std::string BracesCode = R"( 2321 struct A { 2322 int Foo; 2323 }; 2324 2325 struct B { 2326 int Bar; 2327 A Baz; 2328 int Qux; 2329 }; 2330 2331 void target(int BarArg, int FooArg, int QuxArg) { 2332 B Quux{BarArg, {FooArg}, QuxArg}; 2333 /*[[p]]*/ 2334 } 2335 )"; 2336 std::string BraceEllisionCode = R"( 2337 struct A { 2338 int Foo; 2339 }; 2340 2341 struct B { 2342 int Bar; 2343 A Baz; 2344 int Qux; 2345 }; 2346 2347 void target(int BarArg, int FooArg, int QuxArg) { 2348 B Quux = {BarArg, FooArg, QuxArg}; 2349 /*[[p]]*/ 2350 } 2351 )"; 2352 for (const std::string &Code : {BracesCode, BraceEllisionCode}) { 2353 runDataflow( 2354 Code, [](llvm::ArrayRef< 2355 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2356 Results, 2357 ASTContext &ASTCtx) { 2358 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2359 const Environment &Env = Results[0].second.Env; 2360 2361 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2362 ASSERT_THAT(FooDecl, NotNull()); 2363 2364 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2365 ASSERT_THAT(BarDecl, NotNull()); 2366 2367 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2368 ASSERT_THAT(BazDecl, NotNull()); 2369 2370 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2371 ASSERT_THAT(QuxDecl, NotNull()); 2372 2373 const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg"); 2374 ASSERT_THAT(FooArgDecl, NotNull()); 2375 2376 const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg"); 2377 ASSERT_THAT(BarArgDecl, NotNull()); 2378 2379 const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg"); 2380 ASSERT_THAT(QuxArgDecl, NotNull()); 2381 2382 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 2383 ASSERT_THAT(QuuxDecl, NotNull()); 2384 2385 const auto *FooArgVal = 2386 cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None)); 2387 const auto *BarArgVal = 2388 cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None)); 2389 const auto *QuxArgVal = 2390 cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None)); 2391 2392 const auto *QuuxVal = 2393 cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None)); 2394 ASSERT_THAT(QuuxVal, NotNull()); 2395 2396 const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl)); 2397 ASSERT_THAT(BazVal, NotNull()); 2398 2399 EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal); 2400 EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal); 2401 EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal); 2402 }); 2403 } 2404 } 2405 2406 TEST_F(TransferTest, AssignToUnionMember) { 2407 std::string Code = R"( 2408 union A { 2409 int Foo; 2410 }; 2411 2412 void target(int Bar) { 2413 A Baz; 2414 Baz.Foo = Bar; 2415 // [[p]] 2416 } 2417 )"; 2418 runDataflow(Code, 2419 [](llvm::ArrayRef< 2420 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2421 Results, 2422 ASTContext &ASTCtx) { 2423 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2424 const Environment &Env = Results[0].second.Env; 2425 2426 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2427 ASSERT_THAT(BazDecl, NotNull()); 2428 ASSERT_TRUE(BazDecl->getType()->isUnionType()); 2429 2430 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>( 2431 Env.getStorageLocation(*BazDecl, SkipPast::None)); 2432 ASSERT_THAT(BazLoc, NotNull()); 2433 2434 // FIXME: Add support for union types. 2435 EXPECT_THAT(Env.getValue(*BazLoc), IsNull()); 2436 }); 2437 } 2438 2439 TEST_F(TransferTest, AssignFromBoolLiteral) { 2440 std::string Code = R"( 2441 void target() { 2442 bool Foo = true; 2443 bool Bar = false; 2444 // [[p]] 2445 } 2446 )"; 2447 runDataflow(Code, 2448 [](llvm::ArrayRef< 2449 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2450 Results, 2451 ASTContext &ASTCtx) { 2452 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2453 const Environment &Env = Results[0].second.Env; 2454 2455 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2456 ASSERT_THAT(FooDecl, NotNull()); 2457 2458 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2459 Env.getValue(*FooDecl, SkipPast::None)); 2460 ASSERT_THAT(FooVal, NotNull()); 2461 2462 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2463 ASSERT_THAT(BarDecl, NotNull()); 2464 2465 const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>( 2466 Env.getValue(*BarDecl, SkipPast::None)); 2467 ASSERT_THAT(BarVal, NotNull()); 2468 2469 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true)); 2470 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false)); 2471 }); 2472 } 2473 2474 TEST_F(TransferTest, AssignFromCompositeBoolExpression) { 2475 { 2476 std::string Code = R"( 2477 void target(bool Foo, bool Bar, bool Qux) { 2478 bool Baz = (Foo) && (Bar || Qux); 2479 // [[p]] 2480 } 2481 )"; 2482 runDataflow( 2483 Code, [](llvm::ArrayRef< 2484 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2485 Results, 2486 ASTContext &ASTCtx) { 2487 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2488 const Environment &Env = Results[0].second.Env; 2489 2490 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2491 ASSERT_THAT(FooDecl, NotNull()); 2492 2493 const auto *FooVal = dyn_cast_or_null<BoolValue>( 2494 Env.getValue(*FooDecl, SkipPast::None)); 2495 ASSERT_THAT(FooVal, NotNull()); 2496 2497 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2498 ASSERT_THAT(BarDecl, NotNull()); 2499 2500 const auto *BarVal = dyn_cast_or_null<BoolValue>( 2501 Env.getValue(*BarDecl, SkipPast::None)); 2502 ASSERT_THAT(BarVal, NotNull()); 2503 2504 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2505 ASSERT_THAT(QuxDecl, NotNull()); 2506 2507 const auto *QuxVal = dyn_cast_or_null<BoolValue>( 2508 Env.getValue(*QuxDecl, SkipPast::None)); 2509 ASSERT_THAT(QuxVal, NotNull()); 2510 2511 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2512 ASSERT_THAT(BazDecl, NotNull()); 2513 2514 const auto *BazVal = dyn_cast_or_null<ConjunctionValue>( 2515 Env.getValue(*BazDecl, SkipPast::None)); 2516 ASSERT_THAT(BazVal, NotNull()); 2517 EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal); 2518 2519 const auto *BazRightSubValVal = 2520 cast<DisjunctionValue>(&BazVal->getRightSubValue()); 2521 EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal); 2522 EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal); 2523 }); 2524 } 2525 2526 { 2527 std::string Code = R"( 2528 void target(bool Foo, bool Bar, bool Qux) { 2529 bool Baz = (Foo && Qux) || (Bar); 2530 // [[p]] 2531 } 2532 )"; 2533 runDataflow( 2534 Code, [](llvm::ArrayRef< 2535 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2536 Results, 2537 ASTContext &ASTCtx) { 2538 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2539 const Environment &Env = Results[0].second.Env; 2540 2541 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2542 ASSERT_THAT(FooDecl, NotNull()); 2543 2544 const auto *FooVal = dyn_cast_or_null<BoolValue>( 2545 Env.getValue(*FooDecl, SkipPast::None)); 2546 ASSERT_THAT(FooVal, NotNull()); 2547 2548 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2549 ASSERT_THAT(BarDecl, NotNull()); 2550 2551 const auto *BarVal = dyn_cast_or_null<BoolValue>( 2552 Env.getValue(*BarDecl, SkipPast::None)); 2553 ASSERT_THAT(BarVal, NotNull()); 2554 2555 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2556 ASSERT_THAT(QuxDecl, NotNull()); 2557 2558 const auto *QuxVal = dyn_cast_or_null<BoolValue>( 2559 Env.getValue(*QuxDecl, SkipPast::None)); 2560 ASSERT_THAT(QuxVal, NotNull()); 2561 2562 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2563 ASSERT_THAT(BazDecl, NotNull()); 2564 2565 const auto *BazVal = dyn_cast_or_null<DisjunctionValue>( 2566 Env.getValue(*BazDecl, SkipPast::None)); 2567 ASSERT_THAT(BazVal, NotNull()); 2568 2569 const auto *BazLeftSubValVal = 2570 cast<ConjunctionValue>(&BazVal->getLeftSubValue()); 2571 EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal); 2572 EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal); 2573 2574 EXPECT_EQ(&BazVal->getRightSubValue(), BarVal); 2575 }); 2576 } 2577 2578 { 2579 std::string Code = R"( 2580 void target(bool A, bool B, bool C, bool D) { 2581 bool Foo = ((A && B) && C) && D; 2582 // [[p]] 2583 } 2584 )"; 2585 runDataflow( 2586 Code, [](llvm::ArrayRef< 2587 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2588 Results, 2589 ASTContext &ASTCtx) { 2590 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2591 const Environment &Env = Results[0].second.Env; 2592 2593 const ValueDecl *ADecl = findValueDecl(ASTCtx, "A"); 2594 ASSERT_THAT(ADecl, NotNull()); 2595 2596 const auto *AVal = 2597 dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl, SkipPast::None)); 2598 ASSERT_THAT(AVal, NotNull()); 2599 2600 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 2601 ASSERT_THAT(BDecl, NotNull()); 2602 2603 const auto *BVal = 2604 dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl, SkipPast::None)); 2605 ASSERT_THAT(BVal, NotNull()); 2606 2607 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 2608 ASSERT_THAT(CDecl, NotNull()); 2609 2610 const auto *CVal = 2611 dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 2612 ASSERT_THAT(CVal, NotNull()); 2613 2614 const ValueDecl *DDecl = findValueDecl(ASTCtx, "D"); 2615 ASSERT_THAT(DDecl, NotNull()); 2616 2617 const auto *DVal = 2618 dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl, SkipPast::None)); 2619 ASSERT_THAT(DVal, NotNull()); 2620 2621 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2622 ASSERT_THAT(FooDecl, NotNull()); 2623 2624 const auto *FooVal = dyn_cast_or_null<ConjunctionValue>( 2625 Env.getValue(*FooDecl, SkipPast::None)); 2626 ASSERT_THAT(FooVal, NotNull()); 2627 2628 const auto &FooLeftSubVal = 2629 cast<ConjunctionValue>(FooVal->getLeftSubValue()); 2630 const auto &FooLeftLeftSubVal = 2631 cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue()); 2632 EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal); 2633 EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal); 2634 EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal); 2635 EXPECT_EQ(&FooVal->getRightSubValue(), DVal); 2636 }); 2637 } 2638 } 2639 2640 TEST_F(TransferTest, AssignFromBoolNegation) { 2641 std::string Code = R"( 2642 void target() { 2643 bool Foo = true; 2644 bool Bar = !(Foo); 2645 // [[p]] 2646 } 2647 )"; 2648 runDataflow(Code, 2649 [](llvm::ArrayRef< 2650 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2651 Results, 2652 ASTContext &ASTCtx) { 2653 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2654 const Environment &Env = Results[0].second.Env; 2655 2656 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2657 ASSERT_THAT(FooDecl, NotNull()); 2658 2659 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2660 Env.getValue(*FooDecl, SkipPast::None)); 2661 ASSERT_THAT(FooVal, NotNull()); 2662 2663 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2664 ASSERT_THAT(BarDecl, NotNull()); 2665 2666 const auto *BarVal = dyn_cast_or_null<NegationValue>( 2667 Env.getValue(*BarDecl, SkipPast::None)); 2668 ASSERT_THAT(BarVal, NotNull()); 2669 2670 EXPECT_EQ(&BarVal->getSubVal(), FooVal); 2671 }); 2672 } 2673 2674 TEST_F(TransferTest, BuiltinExpect) { 2675 std::string Code = R"( 2676 void target(long Foo) { 2677 long Bar = __builtin_expect(Foo, true); 2678 /*[[p]]*/ 2679 } 2680 )"; 2681 runDataflow(Code, 2682 [](llvm::ArrayRef< 2683 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2684 Results, 2685 ASTContext &ASTCtx) { 2686 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2687 const auto &Env = Results[0].second.Env; 2688 2689 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2690 ASSERT_THAT(FooDecl, NotNull()); 2691 2692 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2693 ASSERT_THAT(BarDecl, NotNull()); 2694 2695 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2696 Env.getValue(*BarDecl, SkipPast::None)); 2697 }); 2698 } 2699 2700 // `__builtin_expect` takes and returns a `long` argument, so other types 2701 // involve casts. This verifies that we identify the input and output in that 2702 // case. 2703 TEST_F(TransferTest, BuiltinExpectBoolArg) { 2704 std::string Code = R"( 2705 void target(bool Foo) { 2706 bool Bar = __builtin_expect(Foo, true); 2707 /*[[p]]*/ 2708 } 2709 )"; 2710 runDataflow(Code, 2711 [](llvm::ArrayRef< 2712 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2713 Results, 2714 ASTContext &ASTCtx) { 2715 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2716 const auto &Env = Results[0].second.Env; 2717 2718 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2719 ASSERT_THAT(FooDecl, NotNull()); 2720 2721 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2722 ASSERT_THAT(BarDecl, NotNull()); 2723 2724 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2725 Env.getValue(*BarDecl, SkipPast::None)); 2726 }); 2727 } 2728 2729 TEST_F(TransferTest, BuiltinUnreachable) { 2730 std::string Code = R"( 2731 void target(bool Foo) { 2732 bool Bar = false; 2733 if (Foo) 2734 Bar = Foo; 2735 else 2736 __builtin_unreachable(); 2737 (void)0; 2738 /*[[p]]*/ 2739 } 2740 )"; 2741 runDataflow(Code, 2742 [](llvm::ArrayRef< 2743 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2744 Results, 2745 ASTContext &ASTCtx) { 2746 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2747 const auto &Env = Results[0].second.Env; 2748 2749 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2750 ASSERT_THAT(FooDecl, NotNull()); 2751 2752 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2753 ASSERT_THAT(BarDecl, NotNull()); 2754 2755 // `__builtin_unreachable` promises that the code is 2756 // unreachable, so the compiler treats the "then" branch as the 2757 // only possible predecessor of this statement. 2758 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2759 Env.getValue(*BarDecl, SkipPast::None)); 2760 }); 2761 } 2762 2763 TEST_F(TransferTest, BuiltinTrap) { 2764 std::string Code = R"( 2765 void target(bool Foo) { 2766 bool Bar = false; 2767 if (Foo) 2768 Bar = Foo; 2769 else 2770 __builtin_trap(); 2771 (void)0; 2772 /*[[p]]*/ 2773 } 2774 )"; 2775 runDataflow(Code, 2776 [](llvm::ArrayRef< 2777 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2778 Results, 2779 ASTContext &ASTCtx) { 2780 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2781 const auto &Env = Results[0].second.Env; 2782 2783 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2784 ASSERT_THAT(FooDecl, NotNull()); 2785 2786 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2787 ASSERT_THAT(BarDecl, NotNull()); 2788 2789 // `__builtin_trap` ensures program termination, so only the 2790 // "then" branch is a predecessor of this statement. 2791 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2792 Env.getValue(*BarDecl, SkipPast::None)); 2793 }); 2794 } 2795 2796 TEST_F(TransferTest, BuiltinDebugTrap) { 2797 std::string Code = R"( 2798 void target(bool Foo) { 2799 bool Bar = false; 2800 if (Foo) 2801 Bar = Foo; 2802 else 2803 __builtin_debugtrap(); 2804 (void)0; 2805 /*[[p]]*/ 2806 } 2807 )"; 2808 runDataflow(Code, 2809 [](llvm::ArrayRef< 2810 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2811 Results, 2812 ASTContext &ASTCtx) { 2813 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2814 const auto &Env = Results[0].second.Env; 2815 2816 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2817 ASSERT_THAT(FooDecl, NotNull()); 2818 2819 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2820 ASSERT_THAT(BarDecl, NotNull()); 2821 2822 // `__builtin_debugtrap` doesn't ensure program termination. 2823 EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None), 2824 Env.getValue(*BarDecl, SkipPast::None)); 2825 }); 2826 } 2827 2828 TEST_F(TransferTest, StaticIntSingleVarDecl) { 2829 std::string Code = R"( 2830 void target() { 2831 static int Foo; 2832 // [[p]] 2833 } 2834 )"; 2835 runDataflow(Code, 2836 [](llvm::ArrayRef< 2837 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2838 Results, 2839 ASTContext &ASTCtx) { 2840 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2841 const Environment &Env = Results[0].second.Env; 2842 2843 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2844 ASSERT_THAT(FooDecl, NotNull()); 2845 2846 const StorageLocation *FooLoc = 2847 Env.getStorageLocation(*FooDecl, SkipPast::None); 2848 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 2849 2850 const Value *FooVal = Env.getValue(*FooLoc); 2851 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 2852 }); 2853 } 2854 2855 TEST_F(TransferTest, StaticIntGroupVarDecl) { 2856 std::string Code = R"( 2857 void target() { 2858 static int Foo, Bar; 2859 (void)0; 2860 // [[p]] 2861 } 2862 )"; 2863 runDataflow(Code, 2864 [](llvm::ArrayRef< 2865 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2866 Results, 2867 ASTContext &ASTCtx) { 2868 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2869 const Environment &Env = Results[0].second.Env; 2870 2871 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2872 ASSERT_THAT(FooDecl, NotNull()); 2873 2874 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2875 ASSERT_THAT(BarDecl, NotNull()); 2876 2877 const StorageLocation *FooLoc = 2878 Env.getStorageLocation(*FooDecl, SkipPast::None); 2879 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 2880 2881 const StorageLocation *BarLoc = 2882 Env.getStorageLocation(*BarDecl, SkipPast::None); 2883 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 2884 2885 const Value *FooVal = Env.getValue(*FooLoc); 2886 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 2887 2888 const Value *BarVal = Env.getValue(*BarLoc); 2889 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 2890 2891 EXPECT_NE(FooVal, BarVal); 2892 }); 2893 } 2894 2895 TEST_F(TransferTest, GlobalIntVarDecl) { 2896 std::string Code = R"( 2897 static int Foo; 2898 2899 void target() { 2900 int Bar = Foo; 2901 int Baz = Foo; 2902 // [[p]] 2903 } 2904 )"; 2905 runDataflow(Code, 2906 [](llvm::ArrayRef< 2907 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2908 Results, 2909 ASTContext &ASTCtx) { 2910 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2911 const Environment &Env = Results[0].second.Env; 2912 2913 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2914 ASSERT_THAT(BarDecl, NotNull()); 2915 2916 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2917 ASSERT_THAT(BazDecl, NotNull()); 2918 2919 const Value *BarVal = 2920 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2921 const Value *BazVal = 2922 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2923 EXPECT_EQ(BarVal, BazVal); 2924 }); 2925 } 2926 2927 TEST_F(TransferTest, StaticMemberIntVarDecl) { 2928 std::string Code = R"( 2929 struct A { 2930 static int Foo; 2931 }; 2932 2933 void target(A a) { 2934 int Bar = a.Foo; 2935 int Baz = a.Foo; 2936 // [[p]] 2937 } 2938 )"; 2939 runDataflow(Code, 2940 [](llvm::ArrayRef< 2941 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2942 Results, 2943 ASTContext &ASTCtx) { 2944 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2945 const Environment &Env = Results[0].second.Env; 2946 2947 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2948 ASSERT_THAT(BarDecl, NotNull()); 2949 2950 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2951 ASSERT_THAT(BazDecl, NotNull()); 2952 2953 const Value *BarVal = 2954 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2955 const Value *BazVal = 2956 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2957 EXPECT_EQ(BarVal, BazVal); 2958 }); 2959 } 2960 2961 TEST_F(TransferTest, StaticMemberRefVarDecl) { 2962 std::string Code = R"( 2963 struct A { 2964 static int &Foo; 2965 }; 2966 2967 void target(A a) { 2968 int Bar = a.Foo; 2969 int Baz = a.Foo; 2970 // [[p]] 2971 } 2972 )"; 2973 runDataflow(Code, 2974 [](llvm::ArrayRef< 2975 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2976 Results, 2977 ASTContext &ASTCtx) { 2978 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2979 const Environment &Env = Results[0].second.Env; 2980 2981 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2982 ASSERT_THAT(BarDecl, NotNull()); 2983 2984 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2985 ASSERT_THAT(BazDecl, NotNull()); 2986 2987 const Value *BarVal = 2988 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2989 const Value *BazVal = 2990 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2991 EXPECT_EQ(BarVal, BazVal); 2992 }); 2993 } 2994 2995 TEST_F(TransferTest, AssignMemberBeforeCopy) { 2996 std::string Code = R"( 2997 struct A { 2998 int Foo; 2999 }; 3000 3001 void target() { 3002 A A1; 3003 A A2; 3004 int Bar; 3005 A1.Foo = Bar; 3006 A2 = A1; 3007 // [[p]] 3008 } 3009 )"; 3010 runDataflow(Code, 3011 [](llvm::ArrayRef< 3012 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3013 Results, 3014 ASTContext &ASTCtx) { 3015 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3016 const Environment &Env = Results[0].second.Env; 3017 3018 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3019 ASSERT_THAT(FooDecl, NotNull()); 3020 3021 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3022 ASSERT_THAT(BarDecl, NotNull()); 3023 3024 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); 3025 ASSERT_THAT(A1Decl, NotNull()); 3026 3027 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); 3028 ASSERT_THAT(A2Decl, NotNull()); 3029 3030 const auto *BarVal = 3031 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3032 3033 const auto *A2Val = 3034 cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None)); 3035 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal); 3036 }); 3037 } 3038 3039 TEST_F(TransferTest, BooleanEquality) { 3040 std::string Code = R"( 3041 void target(bool Bar) { 3042 bool Foo = true; 3043 if (Bar == Foo) { 3044 (void)0; 3045 /*[[p-then]]*/ 3046 } else { 3047 (void)0; 3048 /*[[p-else]]*/ 3049 } 3050 } 3051 )"; 3052 runDataflow( 3053 Code, [](llvm::ArrayRef< 3054 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3055 Results, 3056 ASTContext &ASTCtx) { 3057 ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _))); 3058 const Environment &EnvElse = Results[0].second.Env; 3059 const Environment &EnvThen = Results[1].second.Env; 3060 3061 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3062 ASSERT_THAT(BarDecl, NotNull()); 3063 3064 auto &BarValThen = 3065 *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None)); 3066 EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen)); 3067 3068 auto &BarValElse = 3069 *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None)); 3070 EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse)); 3071 }); 3072 } 3073 3074 TEST_F(TransferTest, BooleanInequality) { 3075 std::string Code = R"( 3076 void target(bool Bar) { 3077 bool Foo = true; 3078 if (Bar != Foo) { 3079 (void)0; 3080 /*[[p-then]]*/ 3081 } else { 3082 (void)0; 3083 /*[[p-else]]*/ 3084 } 3085 } 3086 )"; 3087 runDataflow( 3088 Code, [](llvm::ArrayRef< 3089 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3090 Results, 3091 ASTContext &ASTCtx) { 3092 ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _))); 3093 const Environment &EnvElse = Results[0].second.Env; 3094 const Environment &EnvThen = Results[1].second.Env; 3095 3096 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3097 ASSERT_THAT(BarDecl, NotNull()); 3098 3099 auto &BarValThen = 3100 *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None)); 3101 EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen)); 3102 3103 auto &BarValElse = 3104 *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None)); 3105 EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse)); 3106 }); 3107 } 3108 3109 TEST_F(TransferTest, CorrelatedBranches) { 3110 std::string Code = R"( 3111 void target(bool B, bool C) { 3112 if (B) { 3113 return; 3114 } 3115 (void)0; 3116 /*[[p0]]*/ 3117 if (C) { 3118 B = true; 3119 /*[[p1]]*/ 3120 } 3121 if (B) { 3122 (void)0; 3123 /*[[p2]]*/ 3124 } 3125 } 3126 )"; 3127 runDataflow( 3128 Code, [](llvm::ArrayRef< 3129 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3130 Results, 3131 ASTContext &ASTCtx) { 3132 ASSERT_THAT(Results, SizeIs(3)); 3133 3134 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3135 ASSERT_THAT(CDecl, NotNull()); 3136 3137 { 3138 ASSERT_THAT(Results[2], Pair("p0", _)); 3139 const Environment &Env = Results[2].second.Env; 3140 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3141 ASSERT_THAT(BDecl, NotNull()); 3142 auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None)); 3143 3144 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal))); 3145 } 3146 3147 { 3148 ASSERT_THAT(Results[1], Pair("p1", _)); 3149 const Environment &Env = Results[1].second.Env; 3150 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 3151 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3152 } 3153 3154 { 3155 ASSERT_THAT(Results[0], Pair("p2", _)); 3156 const Environment &Env = Results[0].second.Env; 3157 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 3158 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3159 } 3160 }); 3161 } 3162 3163 TEST_F(TransferTest, LoopWithAssignmentConverges) { 3164 std::string Code = R"( 3165 3166 bool &foo(); 3167 3168 void target() { 3169 do { 3170 bool Bar = foo(); 3171 if (Bar) break; 3172 (void)Bar; 3173 /*[[p]]*/ 3174 } while (true); 3175 } 3176 )"; 3177 // The key property that we are verifying is implicit in `runDataflow` -- 3178 // namely, that the analysis succeeds, rather than hitting the maximum number 3179 // of iterations. 3180 runDataflow( 3181 Code, [](llvm::ArrayRef< 3182 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3183 Results, 3184 ASTContext &ASTCtx) { 3185 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3186 const Environment &Env = Results[0].second.Env; 3187 3188 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3189 ASSERT_THAT(BarDecl, NotNull()); 3190 3191 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 3192 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3193 }); 3194 } 3195 3196 TEST_F(TransferTest, LoopWithReferenceAssignmentConverges) { 3197 std::string Code = R"( 3198 3199 bool &foo(); 3200 3201 void target() { 3202 do { 3203 bool& Bar = foo(); 3204 if (Bar) break; 3205 (void)Bar; 3206 /*[[p]]*/ 3207 } while (true); 3208 } 3209 )"; 3210 // The key property that we are verifying is implicit in `runDataflow` -- 3211 // namely, that the analysis succeeds, rather than hitting the maximum number 3212 // of iterations. 3213 runDataflow( 3214 Code, [](llvm::ArrayRef< 3215 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3216 Results, 3217 ASTContext &ASTCtx) { 3218 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3219 const Environment &Env = Results[0].second.Env; 3220 3221 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3222 ASSERT_THAT(BarDecl, NotNull()); 3223 3224 auto &BarVal = 3225 *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference)); 3226 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3227 }); 3228 } 3229 3230 TEST_F(TransferTest, LoopWithStructReferenceAssignmentConverges) { 3231 std::string Code = R"( 3232 struct Lookup { 3233 int x; 3234 }; 3235 3236 void target(Lookup val, bool b) { 3237 const Lookup* l = nullptr; 3238 while (b) { 3239 l = &val; 3240 /*[[p-inner]]*/ 3241 } 3242 (void)0; 3243 /*[[p-outer]]*/ 3244 } 3245 )"; 3246 // The key property that we are verifying is implicit in `runDataflow` -- 3247 // namely, that the analysis succeeds, rather than hitting the maximum number 3248 // of iterations. 3249 runDataflow( 3250 Code, [](llvm::ArrayRef< 3251 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3252 Results, 3253 ASTContext &ASTCtx) { 3254 ASSERT_THAT(Results, 3255 ElementsAre(Pair("p-outer", _), Pair("p-inner", _))); 3256 const Environment &OuterEnv = Results[0].second.Env; 3257 const Environment &InnerEnv = Results[1].second.Env; 3258 3259 const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val"); 3260 ASSERT_THAT(ValDecl, NotNull()); 3261 3262 const ValueDecl *LDecl = findValueDecl(ASTCtx, "l"); 3263 ASSERT_THAT(LDecl, NotNull()); 3264 3265 // Inner. 3266 auto *LVal = dyn_cast<IndirectionValue>( 3267 InnerEnv.getValue(*LDecl, SkipPast::None)); 3268 ASSERT_THAT(LVal, NotNull()); 3269 3270 EXPECT_EQ(&LVal->getPointeeLoc(), 3271 InnerEnv.getStorageLocation(*ValDecl, SkipPast::Reference)); 3272 3273 // Outer. 3274 LVal = dyn_cast<IndirectionValue>( 3275 OuterEnv.getValue(*LDecl, SkipPast::None)); 3276 ASSERT_THAT(LVal, NotNull()); 3277 3278 // The loop body may not have been executed, so we should not conclude 3279 // that `l` points to `val`. 3280 EXPECT_NE(&LVal->getPointeeLoc(), 3281 OuterEnv.getStorageLocation(*ValDecl, SkipPast::Reference)); 3282 }); 3283 } 3284 3285 TEST_F(TransferTest, DoesNotCrashOnUnionThisExpr) { 3286 std::string Code = R"( 3287 union Union { 3288 int A; 3289 float B; 3290 }; 3291 3292 void foo() { 3293 Union A; 3294 Union B; 3295 A = B; 3296 } 3297 )"; 3298 // This is a crash regression test when calling the transfer function on a 3299 // `CXXThisExpr` that refers to a union. 3300 runDataflow( 3301 Code, 3302 [](llvm::ArrayRef< 3303 std::pair<std::string, DataflowAnalysisState<NoopLattice>>>, 3304 ASTContext &) {}, 3305 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator="); 3306 } 3307 3308 } // namespace 3309