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