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 "TestingSupport.h" 10 #include "clang/AST/ASTContext.h" 11 #include "clang/AST/Decl.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 13 #include "clang/ASTMatchers/ASTMatchers.h" 14 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" 15 #include "clang/Analysis/FlowSensitive/NoopAnalysis.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 template <typename Matcher> 41 void runDataflow(llvm::StringRef Code, Matcher Match, 42 DataflowAnalysisOptions Options, 43 LangStandard::Kind Std = LangStandard::lang_cxx17, 44 llvm::StringRef TargetFun = "target") { 45 ASSERT_THAT_ERROR( 46 test::checkDataflow<NoopAnalysis>( 47 Code, TargetFun, 48 [Options](ASTContext &C, Environment &) { 49 return NoopAnalysis(C, Options); 50 }, 51 [&Match]( 52 llvm::ArrayRef< 53 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 54 Results, 55 ASTContext &ASTCtx) { Match(Results, ASTCtx); }, 56 {"-fsyntax-only", "-fno-delayed-template-parsing", 57 "-std=" + std::string( 58 LangStandard::getLangStandardForKind(Std).getName())}), 59 llvm::Succeeded()); 60 } 61 62 template <typename Matcher> 63 void runDataflow(llvm::StringRef Code, Matcher Match, 64 LangStandard::Kind Std = LangStandard::lang_cxx17, 65 bool ApplyBuiltinTransfer = true, 66 llvm::StringRef TargetFun = "target") { 67 runDataflow(Code, Match, 68 {ApplyBuiltinTransfer ? TransferOptions{} 69 : llvm::Optional<TransferOptions>()}, 70 Std, TargetFun); 71 } 72 73 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) { 74 std::string Code = R"( 75 void target() { 76 int Foo; 77 // [[p]] 78 } 79 )"; 80 runDataflow( 81 Code, 82 [](llvm::ArrayRef< 83 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 84 Results, 85 ASTContext &ASTCtx) { 86 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 87 const Environment &Env = Results[0].second.Env; 88 89 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 90 ASSERT_THAT(FooDecl, NotNull()); 91 92 EXPECT_EQ(Env.getStorageLocation(*FooDecl, SkipPast::None), nullptr); 93 }, 94 LangStandard::lang_cxx17, 95 /*ApplyBuiltinTransfer=*/false); 96 } 97 98 TEST(TransferTest, BoolVarDecl) { 99 std::string Code = R"( 100 void target() { 101 bool Foo; 102 // [[p]] 103 } 104 )"; 105 runDataflow(Code, 106 [](llvm::ArrayRef< 107 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 108 Results, 109 ASTContext &ASTCtx) { 110 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 111 const Environment &Env = Results[0].second.Env; 112 113 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 114 ASSERT_THAT(FooDecl, NotNull()); 115 116 const StorageLocation *FooLoc = 117 Env.getStorageLocation(*FooDecl, SkipPast::None); 118 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 119 120 const Value *FooVal = Env.getValue(*FooLoc); 121 EXPECT_TRUE(isa_and_nonnull<BoolValue>(FooVal)); 122 }); 123 } 124 125 TEST(TransferTest, IntVarDecl) { 126 std::string Code = R"( 127 void target() { 128 int Foo; 129 // [[p]] 130 } 131 )"; 132 runDataflow(Code, 133 [](llvm::ArrayRef< 134 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 135 Results, 136 ASTContext &ASTCtx) { 137 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 138 const Environment &Env = Results[0].second.Env; 139 140 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 141 ASSERT_THAT(FooDecl, NotNull()); 142 143 const StorageLocation *FooLoc = 144 Env.getStorageLocation(*FooDecl, SkipPast::None); 145 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 146 147 const Value *FooVal = Env.getValue(*FooLoc); 148 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 149 }); 150 } 151 152 TEST(TransferTest, StructVarDecl) { 153 std::string Code = R"( 154 struct A { 155 int Bar; 156 }; 157 158 void target() { 159 A Foo; 160 // [[p]] 161 } 162 )"; 163 runDataflow( 164 Code, [](llvm::ArrayRef< 165 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 166 Results, 167 ASTContext &ASTCtx) { 168 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 169 const Environment &Env = Results[0].second.Env; 170 171 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 172 ASSERT_THAT(FooDecl, NotNull()); 173 174 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 175 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 176 177 FieldDecl *BarDecl = nullptr; 178 for (FieldDecl *Field : FooFields) { 179 if (Field->getNameAsString() == "Bar") { 180 BarDecl = Field; 181 } else { 182 FAIL() << "Unexpected field: " << Field->getNameAsString(); 183 } 184 } 185 ASSERT_THAT(BarDecl, NotNull()); 186 187 const auto *FooLoc = cast<AggregateStorageLocation>( 188 Env.getStorageLocation(*FooDecl, SkipPast::None)); 189 const auto *BarLoc = 190 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 191 192 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 193 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 194 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 195 }); 196 } 197 198 TEST(TransferTest, StructVarDeclWithInit) { 199 std::string Code = R"( 200 struct A { 201 int Bar; 202 }; 203 204 A Gen(); 205 206 void target() { 207 A Foo = Gen(); 208 // [[p]] 209 } 210 )"; 211 runDataflow( 212 Code, [](llvm::ArrayRef< 213 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 214 Results, 215 ASTContext &ASTCtx) { 216 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 217 const Environment &Env = Results[0].second.Env; 218 219 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 220 ASSERT_THAT(FooDecl, NotNull()); 221 222 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 223 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 224 225 FieldDecl *BarDecl = nullptr; 226 for (FieldDecl *Field : FooFields) { 227 if (Field->getNameAsString() == "Bar") { 228 BarDecl = Field; 229 } else { 230 FAIL() << "Unexpected field: " << Field->getNameAsString(); 231 } 232 } 233 ASSERT_THAT(BarDecl, NotNull()); 234 235 const auto *FooLoc = cast<AggregateStorageLocation>( 236 Env.getStorageLocation(*FooDecl, SkipPast::None)); 237 const auto *BarLoc = 238 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 239 240 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 241 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 242 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 243 }); 244 } 245 246 TEST(TransferTest, ClassVarDecl) { 247 std::string Code = R"( 248 class A { 249 int Bar; 250 }; 251 252 void target() { 253 A Foo; 254 // [[p]] 255 } 256 )"; 257 runDataflow( 258 Code, [](llvm::ArrayRef< 259 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 260 Results, 261 ASTContext &ASTCtx) { 262 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 263 const Environment &Env = Results[0].second.Env; 264 265 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 266 ASSERT_THAT(FooDecl, NotNull()); 267 268 ASSERT_TRUE(FooDecl->getType()->isClassType()); 269 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 270 271 FieldDecl *BarDecl = nullptr; 272 for (FieldDecl *Field : FooFields) { 273 if (Field->getNameAsString() == "Bar") { 274 BarDecl = Field; 275 } else { 276 FAIL() << "Unexpected field: " << Field->getNameAsString(); 277 } 278 } 279 ASSERT_THAT(BarDecl, NotNull()); 280 281 const auto *FooLoc = cast<AggregateStorageLocation>( 282 Env.getStorageLocation(*FooDecl, SkipPast::None)); 283 const auto *BarLoc = 284 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 285 286 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 287 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 288 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 289 }); 290 } 291 292 TEST(TransferTest, ReferenceVarDecl) { 293 std::string Code = R"( 294 struct A {}; 295 296 A &getA(); 297 298 void target() { 299 A &Foo = getA(); 300 // [[p]] 301 } 302 )"; 303 runDataflow( 304 Code, [](llvm::ArrayRef< 305 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 306 Results, 307 ASTContext &ASTCtx) { 308 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 309 const Environment &Env = Results[0].second.Env; 310 311 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 312 ASSERT_THAT(FooDecl, NotNull()); 313 314 const StorageLocation *FooLoc = 315 Env.getStorageLocation(*FooDecl, SkipPast::None); 316 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 317 318 const ReferenceValue *FooVal = 319 cast<ReferenceValue>(Env.getValue(*FooLoc)); 320 const StorageLocation &FooReferentLoc = FooVal->getReferentLoc(); 321 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooReferentLoc)); 322 323 const Value *FooReferentVal = Env.getValue(FooReferentLoc); 324 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal)); 325 }); 326 } 327 328 TEST(TransferTest, SelfReferentialReferenceVarDecl) { 329 std::string Code = R"( 330 struct A; 331 332 struct B {}; 333 334 struct C { 335 A &FooRef; 336 A *FooPtr; 337 B &BazRef; 338 B *BazPtr; 339 }; 340 341 struct A { 342 C &Bar; 343 }; 344 345 A &getA(); 346 347 void target() { 348 A &Foo = getA(); 349 // [[p]] 350 } 351 )"; 352 runDataflow(Code, [](llvm::ArrayRef<std::pair< 353 std::string, DataflowAnalysisState<NoopLattice>>> 354 Results, 355 ASTContext &ASTCtx) { 356 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 357 const Environment &Env = Results[0].second.Env; 358 359 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 360 ASSERT_THAT(FooDecl, NotNull()); 361 362 ASSERT_TRUE(FooDecl->getType()->isReferenceType()); 363 ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType()); 364 const auto FooFields = 365 FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields(); 366 367 FieldDecl *BarDecl = nullptr; 368 for (FieldDecl *Field : FooFields) { 369 if (Field->getNameAsString() == "Bar") { 370 BarDecl = Field; 371 } else { 372 FAIL() << "Unexpected field: " << Field->getNameAsString(); 373 } 374 } 375 ASSERT_THAT(BarDecl, NotNull()); 376 377 ASSERT_TRUE(BarDecl->getType()->isReferenceType()); 378 ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType()); 379 const auto BarFields = 380 BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields(); 381 382 FieldDecl *FooRefDecl = nullptr; 383 FieldDecl *FooPtrDecl = nullptr; 384 FieldDecl *BazRefDecl = nullptr; 385 FieldDecl *BazPtrDecl = nullptr; 386 for (FieldDecl *Field : BarFields) { 387 if (Field->getNameAsString() == "FooRef") { 388 FooRefDecl = Field; 389 } else if (Field->getNameAsString() == "FooPtr") { 390 FooPtrDecl = Field; 391 } else if (Field->getNameAsString() == "BazRef") { 392 BazRefDecl = Field; 393 } else if (Field->getNameAsString() == "BazPtr") { 394 BazPtrDecl = Field; 395 } else { 396 FAIL() << "Unexpected field: " << Field->getNameAsString(); 397 } 398 } 399 ASSERT_THAT(FooRefDecl, NotNull()); 400 ASSERT_THAT(FooPtrDecl, NotNull()); 401 ASSERT_THAT(BazRefDecl, NotNull()); 402 ASSERT_THAT(BazPtrDecl, NotNull()); 403 404 const auto *FooLoc = cast<ScalarStorageLocation>( 405 Env.getStorageLocation(*FooDecl, SkipPast::None)); 406 const auto *FooVal = cast<ReferenceValue>(Env.getValue(*FooLoc)); 407 const auto *FooReferentVal = 408 cast<StructValue>(Env.getValue(FooVal->getReferentLoc())); 409 410 const auto *BarVal = 411 cast<ReferenceValue>(FooReferentVal->getChild(*BarDecl)); 412 const auto *BarReferentVal = 413 cast<StructValue>(Env.getValue(BarVal->getReferentLoc())); 414 415 const auto *FooRefVal = 416 cast<ReferenceValue>(BarReferentVal->getChild(*FooRefDecl)); 417 const StorageLocation &FooReferentLoc = FooRefVal->getReferentLoc(); 418 EXPECT_THAT(Env.getValue(FooReferentLoc), IsNull()); 419 420 const auto *FooPtrVal = 421 cast<PointerValue>(BarReferentVal->getChild(*FooPtrDecl)); 422 const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc(); 423 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull()); 424 425 const auto *BazRefVal = 426 cast<ReferenceValue>(BarReferentVal->getChild(*BazRefDecl)); 427 const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc(); 428 EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull()); 429 430 const auto *BazPtrVal = 431 cast<PointerValue>(BarReferentVal->getChild(*BazPtrDecl)); 432 const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc(); 433 EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); 434 }); 435 } 436 437 TEST(TransferTest, PointerVarDecl) { 438 std::string Code = R"( 439 struct A {}; 440 441 A *getA(); 442 443 void target() { 444 A *Foo = getA(); 445 // [[p]] 446 } 447 )"; 448 runDataflow( 449 Code, [](llvm::ArrayRef< 450 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 451 Results, 452 ASTContext &ASTCtx) { 453 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 454 const Environment &Env = Results[0].second.Env; 455 456 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 457 ASSERT_THAT(FooDecl, NotNull()); 458 459 const StorageLocation *FooLoc = 460 Env.getStorageLocation(*FooDecl, SkipPast::None); 461 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 462 463 const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 464 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 465 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 466 467 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 468 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 469 }); 470 } 471 472 TEST(TransferTest, SelfReferentialPointerVarDecl) { 473 std::string Code = R"( 474 struct A; 475 476 struct B {}; 477 478 struct C { 479 A &FooRef; 480 A *FooPtr; 481 B &BazRef; 482 B *BazPtr; 483 }; 484 485 struct A { 486 C *Bar; 487 }; 488 489 A *getA(); 490 491 void target() { 492 A *Foo = getA(); 493 // [[p]] 494 } 495 )"; 496 runDataflow( 497 Code, [](llvm::ArrayRef< 498 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 499 Results, 500 ASTContext &ASTCtx) { 501 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 502 const Environment &Env = Results[0].second.Env; 503 504 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 505 ASSERT_THAT(FooDecl, NotNull()); 506 507 ASSERT_TRUE(FooDecl->getType()->isPointerType()); 508 ASSERT_TRUE(FooDecl->getType() 509 ->getAs<PointerType>() 510 ->getPointeeType() 511 ->isStructureType()); 512 const auto FooFields = FooDecl->getType() 513 ->getAs<PointerType>() 514 ->getPointeeType() 515 ->getAsRecordDecl() 516 ->fields(); 517 518 FieldDecl *BarDecl = nullptr; 519 for (FieldDecl *Field : FooFields) { 520 if (Field->getNameAsString() == "Bar") { 521 BarDecl = Field; 522 } else { 523 FAIL() << "Unexpected field: " << Field->getNameAsString(); 524 } 525 } 526 ASSERT_THAT(BarDecl, NotNull()); 527 528 ASSERT_TRUE(BarDecl->getType()->isPointerType()); 529 ASSERT_TRUE(BarDecl->getType() 530 ->getAs<PointerType>() 531 ->getPointeeType() 532 ->isStructureType()); 533 const auto BarFields = BarDecl->getType() 534 ->getAs<PointerType>() 535 ->getPointeeType() 536 ->getAsRecordDecl() 537 ->fields(); 538 539 FieldDecl *FooRefDecl = nullptr; 540 FieldDecl *FooPtrDecl = nullptr; 541 FieldDecl *BazRefDecl = nullptr; 542 FieldDecl *BazPtrDecl = nullptr; 543 for (FieldDecl *Field : BarFields) { 544 if (Field->getNameAsString() == "FooRef") { 545 FooRefDecl = Field; 546 } else if (Field->getNameAsString() == "FooPtr") { 547 FooPtrDecl = Field; 548 } else if (Field->getNameAsString() == "BazRef") { 549 BazRefDecl = Field; 550 } else if (Field->getNameAsString() == "BazPtr") { 551 BazPtrDecl = Field; 552 } else { 553 FAIL() << "Unexpected field: " << Field->getNameAsString(); 554 } 555 } 556 ASSERT_THAT(FooRefDecl, NotNull()); 557 ASSERT_THAT(FooPtrDecl, NotNull()); 558 ASSERT_THAT(BazRefDecl, NotNull()); 559 ASSERT_THAT(BazPtrDecl, NotNull()); 560 561 const auto *FooLoc = cast<ScalarStorageLocation>( 562 Env.getStorageLocation(*FooDecl, SkipPast::None)); 563 const auto *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 564 const auto *FooPointeeVal = 565 cast<StructValue>(Env.getValue(FooVal->getPointeeLoc())); 566 567 const auto *BarVal = 568 cast<PointerValue>(FooPointeeVal->getChild(*BarDecl)); 569 const auto *BarPointeeVal = 570 cast<StructValue>(Env.getValue(BarVal->getPointeeLoc())); 571 572 const auto *FooRefVal = 573 cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl)); 574 const StorageLocation &FooReferentLoc = FooRefVal->getReferentLoc(); 575 EXPECT_THAT(Env.getValue(FooReferentLoc), IsNull()); 576 577 const auto *FooPtrVal = 578 cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl)); 579 const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc(); 580 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull()); 581 582 const auto *BazRefVal = 583 cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl)); 584 const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc(); 585 EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull()); 586 587 const auto *BazPtrVal = 588 cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl)); 589 const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc(); 590 EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); 591 }); 592 } 593 594 TEST(TransferTest, MultipleVarsDecl) { 595 std::string Code = R"( 596 void target() { 597 int Foo, Bar; 598 (void)0; 599 // [[p]] 600 } 601 )"; 602 runDataflow(Code, 603 [](llvm::ArrayRef< 604 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 605 Results, 606 ASTContext &ASTCtx) { 607 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 608 const Environment &Env = Results[0].second.Env; 609 610 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 611 ASSERT_THAT(FooDecl, NotNull()); 612 613 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 614 ASSERT_THAT(BarDecl, NotNull()); 615 616 const StorageLocation *FooLoc = 617 Env.getStorageLocation(*FooDecl, SkipPast::None); 618 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 619 620 const StorageLocation *BarLoc = 621 Env.getStorageLocation(*BarDecl, SkipPast::None); 622 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 623 624 const Value *FooVal = Env.getValue(*FooLoc); 625 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 626 627 const Value *BarVal = Env.getValue(*BarLoc); 628 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 629 }); 630 } 631 632 TEST(TransferTest, JoinVarDecl) { 633 std::string Code = R"( 634 void target(bool B) { 635 int Foo; 636 // [[p1]] 637 if (B) { 638 int Bar; 639 // [[p2]] 640 } else { 641 int Baz; 642 // [[p3]] 643 } 644 (void)0; 645 // [[p4]] 646 } 647 )"; 648 runDataflow(Code, [](llvm::ArrayRef<std::pair< 649 std::string, DataflowAnalysisState<NoopLattice>>> 650 Results, 651 ASTContext &ASTCtx) { 652 ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _), 653 Pair("p2", _), Pair("p1", _))); 654 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 655 ASSERT_THAT(FooDecl, NotNull()); 656 657 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 658 ASSERT_THAT(BarDecl, NotNull()); 659 660 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 661 ASSERT_THAT(BazDecl, NotNull()); 662 663 const Environment &Env1 = Results[3].second.Env; 664 const StorageLocation *FooLoc = 665 Env1.getStorageLocation(*FooDecl, SkipPast::None); 666 EXPECT_THAT(FooLoc, NotNull()); 667 EXPECT_THAT(Env1.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 668 EXPECT_THAT(Env1.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 669 670 const Environment &Env2 = Results[2].second.Env; 671 EXPECT_EQ(Env2.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 672 EXPECT_THAT(Env2.getStorageLocation(*BarDecl, SkipPast::None), NotNull()); 673 EXPECT_THAT(Env2.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 674 675 const Environment &Env3 = Results[1].second.Env; 676 EXPECT_EQ(Env3.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 677 EXPECT_THAT(Env3.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 678 EXPECT_THAT(Env3.getStorageLocation(*BazDecl, SkipPast::None), NotNull()); 679 680 const Environment &Env4 = Results[0].second.Env; 681 EXPECT_EQ(Env4.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 682 EXPECT_THAT(Env4.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 683 EXPECT_THAT(Env4.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 684 }); 685 } 686 687 TEST(TransferTest, BinaryOperatorAssign) { 688 std::string Code = R"( 689 void target() { 690 int Foo; 691 int Bar; 692 (Bar) = (Foo); 693 // [[p]] 694 } 695 )"; 696 runDataflow(Code, 697 [](llvm::ArrayRef< 698 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 699 Results, 700 ASTContext &ASTCtx) { 701 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 702 const Environment &Env = Results[0].second.Env; 703 704 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 705 ASSERT_THAT(FooDecl, NotNull()); 706 707 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 708 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 709 710 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 711 ASSERT_THAT(BarDecl, NotNull()); 712 713 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 714 }); 715 } 716 717 TEST(TransferTest, VarDeclInitAssign) { 718 std::string Code = R"( 719 void target() { 720 int Foo; 721 int Bar = Foo; 722 // [[p]] 723 } 724 )"; 725 runDataflow(Code, 726 [](llvm::ArrayRef< 727 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 728 Results, 729 ASTContext &ASTCtx) { 730 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 731 const Environment &Env = Results[0].second.Env; 732 733 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 734 ASSERT_THAT(FooDecl, NotNull()); 735 736 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 737 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 738 739 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 740 ASSERT_THAT(BarDecl, NotNull()); 741 742 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 743 }); 744 } 745 746 TEST(TransferTest, VarDeclInitAssignChained) { 747 std::string Code = R"( 748 void target() { 749 int Foo; 750 int Bar; 751 int Baz = (Bar = Foo); 752 // [[p]] 753 } 754 )"; 755 runDataflow(Code, 756 [](llvm::ArrayRef< 757 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 758 Results, 759 ASTContext &ASTCtx) { 760 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 761 const Environment &Env = Results[0].second.Env; 762 763 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 764 ASSERT_THAT(FooDecl, NotNull()); 765 766 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 767 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 768 769 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 770 ASSERT_THAT(BarDecl, NotNull()); 771 772 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 773 ASSERT_THAT(BazDecl, NotNull()); 774 775 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 776 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal); 777 }); 778 } 779 780 TEST(TransferTest, VarDeclInitAssignPtrDeref) { 781 std::string Code = R"( 782 void target() { 783 int Foo; 784 int *Bar; 785 *(Bar) = Foo; 786 int Baz = *(Bar); 787 // [[p]] 788 } 789 )"; 790 runDataflow(Code, 791 [](llvm::ArrayRef< 792 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 793 Results, 794 ASTContext &ASTCtx) { 795 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 796 const Environment &Env = Results[0].second.Env; 797 798 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 799 ASSERT_THAT(FooDecl, NotNull()); 800 801 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 802 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 803 804 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 805 ASSERT_THAT(BarDecl, NotNull()); 806 807 const auto *BarVal = 808 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 809 EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal); 810 811 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 812 ASSERT_THAT(BazDecl, NotNull()); 813 814 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal); 815 }); 816 } 817 818 TEST(TransferTest, AssignToAndFromReference) { 819 std::string Code = R"( 820 void target() { 821 int Foo; 822 int Bar; 823 int &Baz = Foo; 824 // [[p1]] 825 Baz = Bar; 826 int Qux = Baz; 827 int &Quux = Baz; 828 // [[p2]] 829 } 830 )"; 831 runDataflow( 832 Code, [](llvm::ArrayRef< 833 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 834 Results, 835 ASTContext &ASTCtx) { 836 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 837 const Environment &Env1 = Results[0].second.Env; 838 const Environment &Env2 = Results[1].second.Env; 839 840 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 841 ASSERT_THAT(FooDecl, NotNull()); 842 843 const Value *FooVal = Env1.getValue(*FooDecl, SkipPast::None); 844 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 845 846 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 847 ASSERT_THAT(BarDecl, NotNull()); 848 849 const Value *BarVal = Env1.getValue(*BarDecl, SkipPast::None); 850 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 851 852 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 853 ASSERT_THAT(BazDecl, NotNull()); 854 855 EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), FooVal); 856 857 EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BarVal); 858 EXPECT_EQ(Env2.getValue(*FooDecl, SkipPast::None), BarVal); 859 860 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 861 ASSERT_THAT(QuxDecl, NotNull()); 862 EXPECT_EQ(Env2.getValue(*QuxDecl, SkipPast::None), BarVal); 863 864 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 865 ASSERT_THAT(QuuxDecl, NotNull()); 866 EXPECT_EQ(Env2.getValue(*QuuxDecl, SkipPast::Reference), BarVal); 867 }); 868 } 869 870 TEST(TransferTest, MultipleParamDecls) { 871 std::string Code = R"( 872 void target(int Foo, int Bar) { 873 (void)0; 874 // [[p]] 875 } 876 )"; 877 runDataflow(Code, 878 [](llvm::ArrayRef< 879 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 880 Results, 881 ASTContext &ASTCtx) { 882 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 883 const Environment &Env = Results[0].second.Env; 884 885 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 886 ASSERT_THAT(FooDecl, NotNull()); 887 888 const StorageLocation *FooLoc = 889 Env.getStorageLocation(*FooDecl, SkipPast::None); 890 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 891 892 const Value *FooVal = Env.getValue(*FooLoc); 893 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 894 895 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 896 ASSERT_THAT(BarDecl, NotNull()); 897 898 const StorageLocation *BarLoc = 899 Env.getStorageLocation(*BarDecl, SkipPast::None); 900 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 901 902 const Value *BarVal = Env.getValue(*BarLoc); 903 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 904 }); 905 } 906 907 TEST(TransferTest, StructParamDecl) { 908 std::string Code = R"( 909 struct A { 910 int Bar; 911 }; 912 913 void target(A Foo) { 914 (void)0; 915 // [[p]] 916 } 917 )"; 918 runDataflow( 919 Code, [](llvm::ArrayRef< 920 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 921 Results, 922 ASTContext &ASTCtx) { 923 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 924 const Environment &Env = Results[0].second.Env; 925 926 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 927 ASSERT_THAT(FooDecl, NotNull()); 928 929 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 930 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 931 932 FieldDecl *BarDecl = nullptr; 933 for (FieldDecl *Field : FooFields) { 934 if (Field->getNameAsString() == "Bar") { 935 BarDecl = Field; 936 } else { 937 FAIL() << "Unexpected field: " << Field->getNameAsString(); 938 } 939 } 940 ASSERT_THAT(BarDecl, NotNull()); 941 942 const auto *FooLoc = cast<AggregateStorageLocation>( 943 Env.getStorageLocation(*FooDecl, SkipPast::None)); 944 const auto *BarLoc = 945 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 946 947 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 948 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 949 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 950 }); 951 } 952 953 TEST(TransferTest, ReferenceParamDecl) { 954 std::string Code = R"( 955 struct A {}; 956 957 void target(A &Foo) { 958 (void)0; 959 // [[p]] 960 } 961 )"; 962 runDataflow( 963 Code, [](llvm::ArrayRef< 964 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 965 Results, 966 ASTContext &ASTCtx) { 967 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 968 const Environment &Env = Results[0].second.Env; 969 970 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 971 ASSERT_THAT(FooDecl, NotNull()); 972 973 const StorageLocation *FooLoc = 974 Env.getStorageLocation(*FooDecl, SkipPast::None); 975 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 976 977 const ReferenceValue *FooVal = 978 dyn_cast<ReferenceValue>(Env.getValue(*FooLoc)); 979 ASSERT_THAT(FooVal, NotNull()); 980 981 const StorageLocation &FooReferentLoc = FooVal->getReferentLoc(); 982 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooReferentLoc)); 983 984 const Value *FooReferentVal = Env.getValue(FooReferentLoc); 985 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal)); 986 }); 987 } 988 989 TEST(TransferTest, PointerParamDecl) { 990 std::string Code = R"( 991 struct A {}; 992 993 void target(A *Foo) { 994 (void)0; 995 // [[p]] 996 } 997 )"; 998 runDataflow( 999 Code, [](llvm::ArrayRef< 1000 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1001 Results, 1002 ASTContext &ASTCtx) { 1003 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1004 const Environment &Env = Results[0].second.Env; 1005 1006 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1007 ASSERT_THAT(FooDecl, NotNull()); 1008 1009 const StorageLocation *FooLoc = 1010 Env.getStorageLocation(*FooDecl, SkipPast::None); 1011 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 1012 1013 const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 1014 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 1015 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 1016 1017 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 1018 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 1019 }); 1020 } 1021 1022 TEST(TransferTest, StructMember) { 1023 std::string Code = R"( 1024 struct A { 1025 int Bar; 1026 }; 1027 1028 void target(A Foo) { 1029 int Baz = Foo.Bar; 1030 // [[p]] 1031 } 1032 )"; 1033 runDataflow( 1034 Code, [](llvm::ArrayRef< 1035 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1036 Results, 1037 ASTContext &ASTCtx) { 1038 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1039 const Environment &Env = Results[0].second.Env; 1040 1041 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1042 ASSERT_THAT(FooDecl, NotNull()); 1043 1044 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1045 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1046 1047 FieldDecl *BarDecl = nullptr; 1048 for (FieldDecl *Field : FooFields) { 1049 if (Field->getNameAsString() == "Bar") { 1050 BarDecl = Field; 1051 } else { 1052 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1053 } 1054 } 1055 ASSERT_THAT(BarDecl, NotNull()); 1056 1057 const auto *FooLoc = cast<AggregateStorageLocation>( 1058 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1059 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1060 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1061 1062 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1063 ASSERT_THAT(BazDecl, NotNull()); 1064 1065 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal); 1066 }); 1067 } 1068 1069 TEST(TransferTest, DerivedBaseMemberClass) { 1070 std::string Code = R"( 1071 class A { 1072 int ADefault; 1073 protected: 1074 int AProtected; 1075 private: 1076 int APrivate; 1077 public: 1078 int APublic; 1079 }; 1080 1081 class B : public A { 1082 int BDefault; 1083 protected: 1084 int BProtected; 1085 private: 1086 int BPrivate; 1087 }; 1088 1089 void target() { 1090 B Foo; 1091 // [[p]] 1092 } 1093 )"; 1094 runDataflow( 1095 Code, [](llvm::ArrayRef< 1096 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1097 Results, 1098 ASTContext &ASTCtx) { 1099 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1100 const Environment &Env = Results[0].second.Env; 1101 1102 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1103 ASSERT_THAT(FooDecl, NotNull()); 1104 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1105 1106 // Derived-class fields. 1107 const FieldDecl *BDefaultDecl = nullptr; 1108 const FieldDecl *BProtectedDecl = nullptr; 1109 const FieldDecl *BPrivateDecl = nullptr; 1110 for (const FieldDecl *Field : 1111 FooDecl->getType()->getAsRecordDecl()->fields()) { 1112 if (Field->getNameAsString() == "BDefault") { 1113 BDefaultDecl = Field; 1114 } else if (Field->getNameAsString() == "BProtected") { 1115 BProtectedDecl = Field; 1116 } else if (Field->getNameAsString() == "BPrivate") { 1117 BPrivateDecl = Field; 1118 } else { 1119 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1120 } 1121 } 1122 ASSERT_THAT(BDefaultDecl, NotNull()); 1123 ASSERT_THAT(BProtectedDecl, NotNull()); 1124 ASSERT_THAT(BPrivateDecl, NotNull()); 1125 1126 // Base-class fields. 1127 const FieldDecl *ADefaultDecl = nullptr; 1128 const FieldDecl *APrivateDecl = nullptr; 1129 const FieldDecl *AProtectedDecl = nullptr; 1130 const FieldDecl *APublicDecl = nullptr; 1131 for (const clang::CXXBaseSpecifier &Base : 1132 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1133 QualType BaseType = Base.getType(); 1134 ASSERT_TRUE(BaseType->isRecordType()); 1135 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1136 if (Field->getNameAsString() == "ADefault") { 1137 ADefaultDecl = Field; 1138 } else if (Field->getNameAsString() == "AProtected") { 1139 AProtectedDecl = Field; 1140 } else if (Field->getNameAsString() == "APrivate") { 1141 APrivateDecl = Field; 1142 } else if (Field->getNameAsString() == "APublic") { 1143 APublicDecl = Field; 1144 } else { 1145 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1146 } 1147 } 1148 } 1149 ASSERT_THAT(ADefaultDecl, NotNull()); 1150 ASSERT_THAT(AProtectedDecl, NotNull()); 1151 ASSERT_THAT(APrivateDecl, NotNull()); 1152 ASSERT_THAT(APublicDecl, NotNull()); 1153 1154 const auto &FooLoc = *cast<AggregateStorageLocation>( 1155 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1156 const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc)); 1157 1158 // Note: we can't test presence of children in `FooLoc`, because 1159 // `getChild` requires its argument be present (or fails an assert). So, 1160 // we limit to testing presence in `FooVal` and coherence between the 1161 // two. 1162 1163 // Base-class fields. 1164 EXPECT_THAT(FooVal.getChild(*ADefaultDecl), NotNull()); 1165 EXPECT_THAT(FooVal.getChild(*APrivateDecl), NotNull()); 1166 1167 EXPECT_THAT(FooVal.getChild(*AProtectedDecl), NotNull()); 1168 EXPECT_EQ(Env.getValue(FooLoc.getChild(*APublicDecl)), 1169 FooVal.getChild(*APublicDecl)); 1170 EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull()); 1171 EXPECT_EQ(Env.getValue(FooLoc.getChild(*AProtectedDecl)), 1172 FooVal.getChild(*AProtectedDecl)); 1173 1174 // Derived-class fields. 1175 EXPECT_THAT(FooVal.getChild(*BDefaultDecl), NotNull()); 1176 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BDefaultDecl)), 1177 FooVal.getChild(*BDefaultDecl)); 1178 EXPECT_THAT(FooVal.getChild(*BProtectedDecl), NotNull()); 1179 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BProtectedDecl)), 1180 FooVal.getChild(*BProtectedDecl)); 1181 EXPECT_THAT(FooVal.getChild(*BPrivateDecl), NotNull()); 1182 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BPrivateDecl)), 1183 FooVal.getChild(*BPrivateDecl)); 1184 }); 1185 } 1186 1187 static void derivedBaseMemberExpectations( 1188 llvm::ArrayRef<std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1189 Results, 1190 ASTContext &ASTCtx) { 1191 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1192 const Environment &Env = Results[0].second.Env; 1193 1194 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1195 ASSERT_THAT(FooDecl, NotNull()); 1196 1197 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1198 const FieldDecl *BarDecl = nullptr; 1199 for (const clang::CXXBaseSpecifier &Base : 1200 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1201 QualType BaseType = Base.getType(); 1202 ASSERT_TRUE(BaseType->isStructureType()); 1203 1204 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1205 if (Field->getNameAsString() == "Bar") { 1206 BarDecl = Field; 1207 } else { 1208 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1209 } 1210 } 1211 } 1212 ASSERT_THAT(BarDecl, NotNull()); 1213 1214 const auto &FooLoc = *cast<AggregateStorageLocation>( 1215 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1216 const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc)); 1217 EXPECT_THAT(FooVal.getChild(*BarDecl), NotNull()); 1218 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BarDecl)), FooVal.getChild(*BarDecl)); 1219 } 1220 1221 TEST(TransferTest, DerivedBaseMemberStructDefault) { 1222 std::string Code = R"( 1223 struct A { 1224 int Bar; 1225 }; 1226 struct B : public A { 1227 }; 1228 1229 void target() { 1230 B Foo; 1231 // [[p]] 1232 } 1233 )"; 1234 runDataflow(Code, derivedBaseMemberExpectations); 1235 } 1236 1237 TEST(TransferTest, DerivedBaseMemberPrivateFriend) { 1238 // Include an access to `Foo.Bar` to verify the analysis doesn't crash on that 1239 // access. 1240 std::string Code = R"( 1241 struct A { 1242 private: 1243 friend void target(); 1244 int Bar; 1245 }; 1246 struct B : public A { 1247 }; 1248 1249 void target() { 1250 B Foo; 1251 (void)Foo.Bar; 1252 // [[p]] 1253 } 1254 )"; 1255 runDataflow(Code, derivedBaseMemberExpectations); 1256 } 1257 1258 TEST(TransferTest, ClassMember) { 1259 std::string Code = R"( 1260 class A { 1261 public: 1262 int Bar; 1263 }; 1264 1265 void target(A Foo) { 1266 int Baz = Foo.Bar; 1267 // [[p]] 1268 } 1269 )"; 1270 runDataflow( 1271 Code, [](llvm::ArrayRef< 1272 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1273 Results, 1274 ASTContext &ASTCtx) { 1275 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1276 const Environment &Env = Results[0].second.Env; 1277 1278 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1279 ASSERT_THAT(FooDecl, NotNull()); 1280 1281 ASSERT_TRUE(FooDecl->getType()->isClassType()); 1282 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1283 1284 FieldDecl *BarDecl = nullptr; 1285 for (FieldDecl *Field : FooFields) { 1286 if (Field->getNameAsString() == "Bar") { 1287 BarDecl = Field; 1288 } else { 1289 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1290 } 1291 } 1292 ASSERT_THAT(BarDecl, NotNull()); 1293 1294 const auto *FooLoc = cast<AggregateStorageLocation>( 1295 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1296 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1297 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1298 1299 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1300 ASSERT_THAT(BazDecl, NotNull()); 1301 1302 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal); 1303 }); 1304 } 1305 1306 TEST(TransferTest, BaseClassInitializer) { 1307 using ast_matchers::cxxConstructorDecl; 1308 using ast_matchers::hasName; 1309 using ast_matchers::ofClass; 1310 1311 std::string Code = R"( 1312 class A { 1313 public: 1314 A(int I) : Bar(I) {} 1315 int Bar; 1316 }; 1317 1318 class B : public A { 1319 public: 1320 B(int I) : A(I) { 1321 (void)0; 1322 // [[p]] 1323 } 1324 }; 1325 )"; 1326 ASSERT_THAT_ERROR( 1327 test::checkDataflow<NoopAnalysis>( 1328 Code, cxxConstructorDecl(ofClass(hasName("B"))), 1329 [](ASTContext &C, Environment &) { 1330 return NoopAnalysis(C, /*ApplyBuiltinTransfer=*/true); 1331 }, 1332 [](llvm::ArrayRef< 1333 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1334 Results, 1335 ASTContext &ASTCtx) { 1336 // Regression test to verify that base-class initializers do not 1337 // trigger an assertion. If we add support for such initializers in 1338 // the future, we can expand this test to check more specific 1339 // properties. 1340 EXPECT_THAT(Results, ElementsAre(Pair("p", _))); 1341 }, 1342 {"-fsyntax-only", "-fno-delayed-template-parsing", 1343 "-std=" + std::string(LangStandard::getLangStandardForKind( 1344 LangStandard::lang_cxx17) 1345 .getName())}), 1346 llvm::Succeeded()); 1347 } 1348 1349 TEST(TransferTest, ReferenceMember) { 1350 std::string Code = R"( 1351 struct A { 1352 int &Bar; 1353 }; 1354 1355 void target(A Foo) { 1356 int Baz = Foo.Bar; 1357 // [[p]] 1358 } 1359 )"; 1360 runDataflow( 1361 Code, [](llvm::ArrayRef< 1362 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1363 Results, 1364 ASTContext &ASTCtx) { 1365 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1366 const Environment &Env = Results[0].second.Env; 1367 1368 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1369 ASSERT_THAT(FooDecl, NotNull()); 1370 1371 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1372 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1373 1374 FieldDecl *BarDecl = nullptr; 1375 for (FieldDecl *Field : FooFields) { 1376 if (Field->getNameAsString() == "Bar") { 1377 BarDecl = Field; 1378 } else { 1379 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1380 } 1381 } 1382 ASSERT_THAT(BarDecl, NotNull()); 1383 1384 const auto *FooLoc = cast<AggregateStorageLocation>( 1385 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1386 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1387 const auto *BarVal = cast<ReferenceValue>(FooVal->getChild(*BarDecl)); 1388 const auto *BarReferentVal = 1389 cast<IntegerValue>(Env.getValue(BarVal->getReferentLoc())); 1390 1391 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1392 ASSERT_THAT(BazDecl, NotNull()); 1393 1394 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarReferentVal); 1395 }); 1396 } 1397 1398 TEST(TransferTest, StructThisMember) { 1399 std::string Code = R"( 1400 struct A { 1401 int Bar; 1402 1403 struct B { 1404 int Baz; 1405 }; 1406 1407 B Qux; 1408 1409 void target() { 1410 int Foo = Bar; 1411 int Quux = Qux.Baz; 1412 // [[p]] 1413 } 1414 }; 1415 )"; 1416 runDataflow( 1417 Code, [](llvm::ArrayRef< 1418 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1419 Results, 1420 ASTContext &ASTCtx) { 1421 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1422 const Environment &Env = Results[0].second.Env; 1423 1424 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1425 Env.getThisPointeeStorageLocation()); 1426 ASSERT_THAT(ThisLoc, NotNull()); 1427 1428 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1429 ASSERT_THAT(BarDecl, NotNull()); 1430 1431 const auto *BarLoc = 1432 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1433 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1434 1435 const Value *BarVal = Env.getValue(*BarLoc); 1436 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1437 1438 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1439 ASSERT_THAT(FooDecl, NotNull()); 1440 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1441 1442 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1443 ASSERT_THAT(QuxDecl, NotNull()); 1444 1445 ASSERT_TRUE(QuxDecl->getType()->isStructureType()); 1446 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1447 1448 FieldDecl *BazDecl = nullptr; 1449 for (FieldDecl *Field : QuxFields) { 1450 if (Field->getNameAsString() == "Baz") { 1451 BazDecl = Field; 1452 } else { 1453 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1454 } 1455 } 1456 ASSERT_THAT(BazDecl, NotNull()); 1457 1458 const auto *QuxLoc = 1459 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1460 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1461 ASSERT_THAT(QuxVal, NotNull()); 1462 1463 const auto *BazLoc = 1464 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1465 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1466 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1467 1468 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1469 ASSERT_THAT(QuuxDecl, NotNull()); 1470 EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal); 1471 }); 1472 } 1473 1474 TEST(TransferTest, ClassThisMember) { 1475 std::string Code = R"( 1476 class A { 1477 int Bar; 1478 1479 class B { 1480 public: 1481 int Baz; 1482 }; 1483 1484 B Qux; 1485 1486 void target() { 1487 int Foo = Bar; 1488 int Quux = Qux.Baz; 1489 // [[p]] 1490 } 1491 }; 1492 )"; 1493 runDataflow( 1494 Code, [](llvm::ArrayRef< 1495 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1496 Results, 1497 ASTContext &ASTCtx) { 1498 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1499 const Environment &Env = Results[0].second.Env; 1500 1501 const auto *ThisLoc = 1502 cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation()); 1503 1504 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1505 ASSERT_THAT(BarDecl, NotNull()); 1506 1507 const auto *BarLoc = 1508 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1509 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1510 1511 const Value *BarVal = Env.getValue(*BarLoc); 1512 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1513 1514 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1515 ASSERT_THAT(FooDecl, NotNull()); 1516 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1517 1518 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1519 ASSERT_THAT(QuxDecl, NotNull()); 1520 1521 ASSERT_TRUE(QuxDecl->getType()->isClassType()); 1522 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1523 1524 FieldDecl *BazDecl = nullptr; 1525 for (FieldDecl *Field : QuxFields) { 1526 if (Field->getNameAsString() == "Baz") { 1527 BazDecl = Field; 1528 } else { 1529 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1530 } 1531 } 1532 ASSERT_THAT(BazDecl, NotNull()); 1533 1534 const auto *QuxLoc = 1535 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1536 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1537 ASSERT_THAT(QuxVal, NotNull()); 1538 1539 const auto *BazLoc = 1540 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1541 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1542 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1543 1544 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1545 ASSERT_THAT(QuuxDecl, NotNull()); 1546 EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal); 1547 }); 1548 } 1549 1550 TEST(TransferTest, StructThisInLambda) { 1551 std::string ThisCaptureCode = R"( 1552 struct A { 1553 void frob() { 1554 [this]() { 1555 int Foo = Bar; 1556 // [[p1]] 1557 }(); 1558 } 1559 1560 int Bar; 1561 }; 1562 )"; 1563 runDataflow( 1564 ThisCaptureCode, 1565 [](llvm::ArrayRef< 1566 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1567 Results, 1568 ASTContext &ASTCtx) { 1569 ASSERT_THAT(Results, ElementsAre(Pair("p1", _))); 1570 const Environment &Env = Results[0].second.Env; 1571 1572 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1573 Env.getThisPointeeStorageLocation()); 1574 ASSERT_THAT(ThisLoc, NotNull()); 1575 1576 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1577 ASSERT_THAT(BarDecl, NotNull()); 1578 1579 const auto *BarLoc = 1580 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1581 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1582 1583 const Value *BarVal = Env.getValue(*BarLoc); 1584 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1585 1586 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1587 ASSERT_THAT(FooDecl, NotNull()); 1588 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1589 }, 1590 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1591 1592 std::string RefCaptureDefaultCode = R"( 1593 struct A { 1594 void frob() { 1595 [&]() { 1596 int Foo = Bar; 1597 // [[p2]] 1598 }(); 1599 } 1600 1601 int Bar; 1602 }; 1603 )"; 1604 runDataflow( 1605 RefCaptureDefaultCode, 1606 [](llvm::ArrayRef< 1607 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1608 Results, 1609 ASTContext &ASTCtx) { 1610 ASSERT_THAT(Results, ElementsAre(Pair("p2", _))); 1611 const Environment &Env = Results[0].second.Env; 1612 1613 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1614 Env.getThisPointeeStorageLocation()); 1615 ASSERT_THAT(ThisLoc, NotNull()); 1616 1617 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1618 ASSERT_THAT(BarDecl, NotNull()); 1619 1620 const auto *BarLoc = 1621 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1622 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1623 1624 const Value *BarVal = Env.getValue(*BarLoc); 1625 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1626 1627 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1628 ASSERT_THAT(FooDecl, NotNull()); 1629 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1630 }, 1631 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1632 1633 std::string FreeFunctionLambdaCode = R"( 1634 void foo() { 1635 int Bar; 1636 [&]() { 1637 int Foo = Bar; 1638 // [[p3]] 1639 }(); 1640 } 1641 )"; 1642 runDataflow( 1643 FreeFunctionLambdaCode, 1644 [](llvm::ArrayRef< 1645 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1646 Results, 1647 ASTContext &ASTCtx) { 1648 ASSERT_THAT(Results, ElementsAre(Pair("p3", _))); 1649 const Environment &Env = Results[0].second.Env; 1650 1651 EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull()); 1652 }, 1653 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1654 } 1655 1656 TEST(TransferTest, ConstructorInitializer) { 1657 std::string Code = R"( 1658 struct target { 1659 int Bar; 1660 1661 target(int Foo) : Bar(Foo) { 1662 int Qux = Bar; 1663 // [[p]] 1664 } 1665 }; 1666 )"; 1667 runDataflow(Code, 1668 [](llvm::ArrayRef< 1669 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1670 Results, 1671 ASTContext &ASTCtx) { 1672 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1673 const Environment &Env = Results[0].second.Env; 1674 1675 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1676 Env.getThisPointeeStorageLocation()); 1677 ASSERT_THAT(ThisLoc, NotNull()); 1678 1679 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1680 ASSERT_THAT(FooDecl, NotNull()); 1681 1682 const auto *FooVal = 1683 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1684 1685 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1686 ASSERT_THAT(QuxDecl, NotNull()); 1687 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1688 }); 1689 } 1690 1691 TEST(TransferTest, DefaultInitializer) { 1692 std::string Code = R"( 1693 struct target { 1694 int Bar; 1695 int Baz = Bar; 1696 1697 target(int Foo) : Bar(Foo) { 1698 int Qux = Baz; 1699 // [[p]] 1700 } 1701 }; 1702 )"; 1703 runDataflow(Code, 1704 [](llvm::ArrayRef< 1705 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1706 Results, 1707 ASTContext &ASTCtx) { 1708 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1709 const Environment &Env = Results[0].second.Env; 1710 1711 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1712 Env.getThisPointeeStorageLocation()); 1713 ASSERT_THAT(ThisLoc, NotNull()); 1714 1715 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1716 ASSERT_THAT(FooDecl, NotNull()); 1717 1718 const auto *FooVal = 1719 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1720 1721 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1722 ASSERT_THAT(QuxDecl, NotNull()); 1723 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1724 }); 1725 } 1726 1727 TEST(TransferTest, DefaultInitializerReference) { 1728 std::string Code = R"( 1729 struct target { 1730 int &Bar; 1731 int &Baz = Bar; 1732 1733 target(int &Foo) : Bar(Foo) { 1734 int &Qux = Baz; 1735 // [[p]] 1736 } 1737 }; 1738 )"; 1739 runDataflow( 1740 Code, [](llvm::ArrayRef< 1741 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1742 Results, 1743 ASTContext &ASTCtx) { 1744 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1745 const Environment &Env = Results[0].second.Env; 1746 1747 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1748 Env.getThisPointeeStorageLocation()); 1749 ASSERT_THAT(ThisLoc, NotNull()); 1750 1751 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1752 ASSERT_THAT(FooDecl, NotNull()); 1753 1754 const auto *FooVal = 1755 cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None)); 1756 1757 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1758 ASSERT_THAT(QuxDecl, NotNull()); 1759 1760 const auto *QuxVal = 1761 cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None)); 1762 EXPECT_EQ(&QuxVal->getReferentLoc(), &FooVal->getReferentLoc()); 1763 }); 1764 } 1765 1766 TEST(TransferTest, TemporaryObject) { 1767 std::string Code = R"( 1768 struct A { 1769 int Bar; 1770 }; 1771 1772 void target() { 1773 A Foo = A(); 1774 // [[p]] 1775 } 1776 )"; 1777 runDataflow( 1778 Code, [](llvm::ArrayRef< 1779 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1780 Results, 1781 ASTContext &ASTCtx) { 1782 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1783 const Environment &Env = Results[0].second.Env; 1784 1785 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1786 ASSERT_THAT(FooDecl, NotNull()); 1787 1788 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1789 ASSERT_THAT(BarDecl, NotNull()); 1790 1791 const auto *FooLoc = cast<AggregateStorageLocation>( 1792 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1793 const auto *BarLoc = 1794 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1795 1796 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1797 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1798 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1799 }); 1800 } 1801 1802 TEST(TransferTest, ElidableConstructor) { 1803 // This test is effectively the same as TransferTest.TemporaryObject, but 1804 // the code is compiled as C++ 14. 1805 std::string Code = R"( 1806 struct A { 1807 int Bar; 1808 }; 1809 1810 void target() { 1811 A Foo = A(); 1812 // [[p]] 1813 } 1814 )"; 1815 runDataflow( 1816 Code, 1817 [](llvm::ArrayRef< 1818 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1819 Results, 1820 ASTContext &ASTCtx) { 1821 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1822 const Environment &Env = Results[0].second.Env; 1823 1824 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1825 ASSERT_THAT(FooDecl, NotNull()); 1826 1827 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1828 ASSERT_THAT(BarDecl, NotNull()); 1829 1830 const auto *FooLoc = cast<AggregateStorageLocation>( 1831 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1832 const auto *BarLoc = 1833 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1834 1835 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1836 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1837 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1838 }, 1839 LangStandard::lang_cxx14); 1840 } 1841 1842 TEST(TransferTest, AssignmentOperator) { 1843 std::string Code = R"( 1844 struct A { 1845 int Baz; 1846 }; 1847 1848 void target() { 1849 A Foo; 1850 A Bar; 1851 // [[p1]] 1852 Foo = Bar; 1853 // [[p2]] 1854 } 1855 )"; 1856 runDataflow( 1857 Code, [](llvm::ArrayRef< 1858 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1859 Results, 1860 ASTContext &ASTCtx) { 1861 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 1862 const Environment &Env1 = Results[0].second.Env; 1863 const Environment &Env2 = Results[1].second.Env; 1864 1865 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1866 ASSERT_THAT(FooDecl, NotNull()); 1867 1868 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1869 ASSERT_THAT(BarDecl, NotNull()); 1870 1871 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1872 ASSERT_THAT(BazDecl, NotNull()); 1873 1874 const auto *FooLoc1 = cast<AggregateStorageLocation>( 1875 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 1876 const auto *BarLoc1 = cast<AggregateStorageLocation>( 1877 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 1878 1879 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 1880 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 1881 EXPECT_NE(FooVal1, BarVal1); 1882 1883 const auto *FooBazVal1 = 1884 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 1885 const auto *BarBazVal1 = 1886 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 1887 EXPECT_NE(FooBazVal1, BarBazVal1); 1888 1889 const auto *FooLoc2 = cast<AggregateStorageLocation>( 1890 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 1891 const auto *BarLoc2 = cast<AggregateStorageLocation>( 1892 Env2.getStorageLocation(*BarDecl, SkipPast::None)); 1893 1894 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 1895 const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2)); 1896 EXPECT_EQ(FooVal2, BarVal2); 1897 1898 const auto *FooBazVal2 = 1899 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 1900 const auto *BarBazVal2 = 1901 cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl))); 1902 EXPECT_EQ(FooBazVal2, BarBazVal2); 1903 }); 1904 } 1905 1906 TEST(TransferTest, CopyConstructor) { 1907 std::string Code = R"( 1908 struct A { 1909 int Baz; 1910 }; 1911 1912 void target() { 1913 A Foo; 1914 A Bar = Foo; 1915 // [[p]] 1916 } 1917 )"; 1918 runDataflow( 1919 Code, [](llvm::ArrayRef< 1920 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1921 Results, 1922 ASTContext &ASTCtx) { 1923 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1924 const Environment &Env = Results[0].second.Env; 1925 1926 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1927 ASSERT_THAT(FooDecl, NotNull()); 1928 1929 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1930 ASSERT_THAT(BarDecl, NotNull()); 1931 1932 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1933 ASSERT_THAT(BazDecl, NotNull()); 1934 1935 const auto *FooLoc = cast<AggregateStorageLocation>( 1936 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1937 const auto *BarLoc = cast<AggregateStorageLocation>( 1938 Env.getStorageLocation(*BarDecl, SkipPast::None)); 1939 1940 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1941 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 1942 EXPECT_EQ(FooVal, BarVal); 1943 1944 const auto *FooBazVal = 1945 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 1946 const auto *BarBazVal = 1947 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 1948 EXPECT_EQ(FooBazVal, BarBazVal); 1949 }); 1950 } 1951 1952 TEST(TransferTest, CopyConstructorWithParens) { 1953 std::string Code = R"( 1954 struct A { 1955 int Baz; 1956 }; 1957 1958 void target() { 1959 A Foo; 1960 A Bar((A(Foo))); 1961 // [[p]] 1962 } 1963 )"; 1964 runDataflow( 1965 Code, [](llvm::ArrayRef< 1966 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1967 Results, 1968 ASTContext &ASTCtx) { 1969 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1970 const Environment &Env = Results[0].second.Env; 1971 1972 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1973 ASSERT_THAT(FooDecl, NotNull()); 1974 1975 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1976 ASSERT_THAT(BarDecl, NotNull()); 1977 1978 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1979 ASSERT_THAT(BazDecl, NotNull()); 1980 1981 const auto *FooLoc = cast<AggregateStorageLocation>( 1982 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1983 const auto *BarLoc = cast<AggregateStorageLocation>( 1984 Env.getStorageLocation(*BarDecl, SkipPast::None)); 1985 1986 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1987 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 1988 EXPECT_EQ(FooVal, BarVal); 1989 1990 const auto *FooBazVal = 1991 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 1992 const auto *BarBazVal = 1993 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 1994 EXPECT_EQ(FooBazVal, BarBazVal); 1995 }); 1996 } 1997 1998 TEST(TransferTest, MoveConstructor) { 1999 std::string Code = R"( 2000 namespace std { 2001 2002 template <typename T> struct remove_reference { using type = T; }; 2003 template <typename T> struct remove_reference<T&> { using type = T; }; 2004 template <typename T> struct remove_reference<T&&> { using type = T; }; 2005 2006 template <typename T> 2007 using remove_reference_t = typename remove_reference<T>::type; 2008 2009 template <typename T> 2010 std::remove_reference_t<T>&& move(T&& x); 2011 2012 } // namespace std 2013 2014 struct A { 2015 int Baz; 2016 }; 2017 2018 void target() { 2019 A Foo; 2020 A Bar; 2021 // [[p1]] 2022 Foo = std::move(Bar); 2023 // [[p2]] 2024 } 2025 )"; 2026 runDataflow( 2027 Code, [](llvm::ArrayRef< 2028 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2029 Results, 2030 ASTContext &ASTCtx) { 2031 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 2032 const Environment &Env1 = Results[0].second.Env; 2033 const Environment &Env2 = Results[1].second.Env; 2034 2035 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2036 ASSERT_THAT(FooDecl, NotNull()); 2037 2038 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2039 ASSERT_THAT(BarDecl, NotNull()); 2040 2041 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2042 ASSERT_THAT(BazDecl, NotNull()); 2043 2044 const auto *FooLoc1 = cast<AggregateStorageLocation>( 2045 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 2046 const auto *BarLoc1 = cast<AggregateStorageLocation>( 2047 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 2048 2049 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 2050 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 2051 EXPECT_NE(FooVal1, BarVal1); 2052 2053 const auto *FooBazVal1 = 2054 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 2055 const auto *BarBazVal1 = 2056 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 2057 EXPECT_NE(FooBazVal1, BarBazVal1); 2058 2059 const auto *FooLoc2 = cast<AggregateStorageLocation>( 2060 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 2061 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 2062 EXPECT_EQ(FooVal2, BarVal1); 2063 2064 const auto *FooBazVal2 = 2065 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 2066 EXPECT_EQ(FooBazVal2, BarBazVal1); 2067 }); 2068 } 2069 2070 TEST(TransferTest, BindTemporary) { 2071 std::string Code = R"( 2072 struct A { 2073 virtual ~A() = default; 2074 2075 int Baz; 2076 }; 2077 2078 void target(A Foo) { 2079 int Bar = A(Foo).Baz; 2080 // [[p]] 2081 } 2082 )"; 2083 runDataflow(Code, 2084 [](llvm::ArrayRef< 2085 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2086 Results, 2087 ASTContext &ASTCtx) { 2088 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2089 const Environment &Env = Results[0].second.Env; 2090 2091 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2092 ASSERT_THAT(FooDecl, NotNull()); 2093 2094 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2095 ASSERT_THAT(BarDecl, NotNull()); 2096 2097 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2098 ASSERT_THAT(BazDecl, NotNull()); 2099 2100 const auto &FooVal = 2101 *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 2102 const auto *BarVal = 2103 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2104 EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl)); 2105 }); 2106 } 2107 2108 TEST(TransferTest, StaticCast) { 2109 std::string Code = R"( 2110 void target(int Foo) { 2111 int Bar = static_cast<int>(Foo); 2112 // [[p]] 2113 } 2114 )"; 2115 runDataflow(Code, 2116 [](llvm::ArrayRef< 2117 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2118 Results, 2119 ASTContext &ASTCtx) { 2120 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2121 const Environment &Env = Results[0].second.Env; 2122 2123 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2124 ASSERT_THAT(FooDecl, NotNull()); 2125 2126 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2127 ASSERT_THAT(BarDecl, NotNull()); 2128 2129 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2130 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2131 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2132 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2133 EXPECT_EQ(FooVal, BarVal); 2134 }); 2135 } 2136 2137 TEST(TransferTest, IntegralCast) { 2138 std::string Code = R"( 2139 void target(int Foo) { 2140 long Bar = Foo; 2141 // [[p]] 2142 } 2143 )"; 2144 runDataflow(Code, 2145 [](llvm::ArrayRef< 2146 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2147 Results, 2148 ASTContext &ASTCtx) { 2149 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2150 const Environment &Env = Results[0].second.Env; 2151 2152 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2153 ASSERT_THAT(FooDecl, NotNull()); 2154 2155 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2156 ASSERT_THAT(BarDecl, NotNull()); 2157 2158 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2159 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2160 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2161 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2162 EXPECT_EQ(FooVal, BarVal); 2163 }); 2164 } 2165 2166 TEST(TransferTest, IntegraltoBooleanCast) { 2167 std::string Code = R"( 2168 void target(int Foo) { 2169 bool Bar = Foo; 2170 // [[p]] 2171 } 2172 )"; 2173 runDataflow(Code, 2174 [](llvm::ArrayRef< 2175 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2176 Results, 2177 ASTContext &ASTCtx) { 2178 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2179 const Environment &Env = Results[0].second.Env; 2180 2181 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2182 ASSERT_THAT(FooDecl, NotNull()); 2183 2184 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2185 ASSERT_THAT(BarDecl, NotNull()); 2186 2187 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2188 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2189 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2190 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2191 }); 2192 } 2193 2194 TEST(TransferTest, IntegralToBooleanCastFromBool) { 2195 std::string Code = R"( 2196 void target(bool Foo) { 2197 int Zab = Foo; 2198 bool Bar = Zab; 2199 // [[p]] 2200 } 2201 )"; 2202 runDataflow(Code, 2203 [](llvm::ArrayRef< 2204 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2205 Results, 2206 ASTContext &ASTCtx) { 2207 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2208 const Environment &Env = Results[0].second.Env; 2209 2210 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2211 ASSERT_THAT(FooDecl, NotNull()); 2212 2213 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2214 ASSERT_THAT(BarDecl, NotNull()); 2215 2216 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2217 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2218 EXPECT_TRUE(isa<BoolValue>(FooVal)); 2219 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2220 EXPECT_EQ(FooVal, BarVal); 2221 }); 2222 } 2223 2224 TEST(TransferTest, NullToPointerCast) { 2225 std::string Code = R"( 2226 using my_nullptr_t = decltype(nullptr); 2227 struct Baz {}; 2228 void target() { 2229 int *FooX = nullptr; 2230 int *FooY = nullptr; 2231 bool **Bar = nullptr; 2232 Baz *Baz = nullptr; 2233 my_nullptr_t Null = 0; 2234 // [[p]] 2235 } 2236 )"; 2237 runDataflow(Code, 2238 [](llvm::ArrayRef< 2239 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2240 Results, 2241 ASTContext &ASTCtx) { 2242 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2243 const Environment &Env = Results[0].second.Env; 2244 2245 const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX"); 2246 ASSERT_THAT(FooXDecl, NotNull()); 2247 2248 const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY"); 2249 ASSERT_THAT(FooYDecl, NotNull()); 2250 2251 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2252 ASSERT_THAT(BarDecl, NotNull()); 2253 2254 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2255 ASSERT_THAT(BazDecl, NotNull()); 2256 2257 const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null"); 2258 ASSERT_THAT(NullDecl, NotNull()); 2259 2260 const auto *FooXVal = 2261 cast<PointerValue>(Env.getValue(*FooXDecl, SkipPast::None)); 2262 const auto *FooYVal = 2263 cast<PointerValue>(Env.getValue(*FooYDecl, SkipPast::None)); 2264 const auto *BarVal = 2265 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2266 const auto *BazVal = 2267 cast<PointerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2268 const auto *NullVal = 2269 cast<PointerValue>(Env.getValue(*NullDecl, SkipPast::None)); 2270 2271 EXPECT_EQ(FooXVal, FooYVal); 2272 EXPECT_NE(FooXVal, BarVal); 2273 EXPECT_NE(FooXVal, BazVal); 2274 EXPECT_NE(BarVal, BazVal); 2275 2276 const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc(); 2277 EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc)); 2278 EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull()); 2279 2280 const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc(); 2281 EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc)); 2282 EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull()); 2283 2284 const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc(); 2285 EXPECT_TRUE(isa<AggregateStorageLocation>(BazPointeeLoc)); 2286 EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull()); 2287 2288 const StorageLocation &NullPointeeLoc = 2289 NullVal->getPointeeLoc(); 2290 EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc)); 2291 EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull()); 2292 }); 2293 } 2294 2295 TEST(TransferTest, NullToMemberPointerCast) { 2296 std::string Code = R"( 2297 struct Foo {}; 2298 void target(Foo *Foo) { 2299 int Foo::*MemberPointer = nullptr; 2300 // [[p]] 2301 } 2302 )"; 2303 runDataflow( 2304 Code, [](llvm::ArrayRef< 2305 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2306 Results, 2307 ASTContext &ASTCtx) { 2308 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2309 const Environment &Env = Results[0].second.Env; 2310 2311 const ValueDecl *MemberPointerDecl = 2312 findValueDecl(ASTCtx, "MemberPointer"); 2313 ASSERT_THAT(MemberPointerDecl, NotNull()); 2314 2315 const auto *MemberPointerVal = cast<PointerValue>( 2316 Env.getValue(*MemberPointerDecl, SkipPast::None)); 2317 2318 const StorageLocation &MemberLoc = MemberPointerVal->getPointeeLoc(); 2319 EXPECT_THAT(Env.getValue(MemberLoc), IsNull()); 2320 }); 2321 } 2322 2323 TEST(TransferTest, AddrOfValue) { 2324 std::string Code = R"( 2325 void target() { 2326 int Foo; 2327 int *Bar = &Foo; 2328 // [[p]] 2329 } 2330 )"; 2331 runDataflow(Code, 2332 [](llvm::ArrayRef< 2333 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2334 Results, 2335 ASTContext &ASTCtx) { 2336 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2337 const Environment &Env = Results[0].second.Env; 2338 2339 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2340 ASSERT_THAT(FooDecl, NotNull()); 2341 2342 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2343 ASSERT_THAT(BarDecl, NotNull()); 2344 2345 const auto *FooLoc = cast<ScalarStorageLocation>( 2346 Env.getStorageLocation(*FooDecl, SkipPast::None)); 2347 const auto *BarVal = 2348 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2349 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc); 2350 }); 2351 } 2352 2353 TEST(TransferTest, AddrOfReference) { 2354 std::string Code = R"( 2355 void target(int *Foo) { 2356 int *Bar = &(*Foo); 2357 // [[p]] 2358 } 2359 )"; 2360 runDataflow(Code, 2361 [](llvm::ArrayRef< 2362 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2363 Results, 2364 ASTContext &ASTCtx) { 2365 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2366 const Environment &Env = Results[0].second.Env; 2367 2368 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2369 ASSERT_THAT(FooDecl, NotNull()); 2370 2371 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2372 ASSERT_THAT(BarDecl, NotNull()); 2373 2374 const auto *FooVal = 2375 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2376 const auto *BarVal = 2377 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2378 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 2379 }); 2380 } 2381 2382 TEST(TransferTest, DerefDependentPtr) { 2383 std::string Code = R"( 2384 template <typename T> 2385 void target(T *Foo) { 2386 T &Bar = *Foo; 2387 /*[[p]]*/ 2388 } 2389 )"; 2390 runDataflow( 2391 Code, [](llvm::ArrayRef< 2392 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2393 Results, 2394 ASTContext &ASTCtx) { 2395 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2396 const Environment &Env = Results[0].second.Env; 2397 2398 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2399 ASSERT_THAT(FooDecl, NotNull()); 2400 2401 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2402 ASSERT_THAT(BarDecl, NotNull()); 2403 2404 const auto *FooVal = 2405 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2406 const auto *BarVal = 2407 cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None)); 2408 EXPECT_EQ(&BarVal->getReferentLoc(), &FooVal->getPointeeLoc()); 2409 }); 2410 } 2411 2412 TEST(TransferTest, VarDeclInitAssignConditionalOperator) { 2413 std::string Code = R"( 2414 struct A {}; 2415 2416 void target(A Foo, A Bar, bool Cond) { 2417 A Baz = Cond ? Foo : Bar; 2418 /*[[p]]*/ 2419 } 2420 )"; 2421 runDataflow( 2422 Code, [](llvm::ArrayRef< 2423 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2424 Results, 2425 ASTContext &ASTCtx) { 2426 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2427 const Environment &Env = Results[0].second.Env; 2428 2429 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2430 ASSERT_THAT(FooDecl, NotNull()); 2431 2432 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2433 ASSERT_THAT(BarDecl, NotNull()); 2434 2435 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2436 ASSERT_THAT(BazDecl, NotNull()); 2437 2438 const auto *FooVal = 2439 cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 2440 const auto *BarVal = 2441 cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None)); 2442 2443 const auto *BazVal = 2444 dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None)); 2445 ASSERT_THAT(BazVal, NotNull()); 2446 2447 EXPECT_NE(BazVal, FooVal); 2448 EXPECT_NE(BazVal, BarVal); 2449 }); 2450 } 2451 2452 TEST(TransferTest, VarDeclInDoWhile) { 2453 std::string Code = R"( 2454 void target(int *Foo) { 2455 do { 2456 int Bar = *Foo; 2457 } while (true); 2458 (void)0; 2459 /*[[p]]*/ 2460 } 2461 )"; 2462 runDataflow(Code, 2463 [](llvm::ArrayRef< 2464 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2465 Results, 2466 ASTContext &ASTCtx) { 2467 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2468 const Environment &Env = Results[0].second.Env; 2469 2470 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2471 ASSERT_THAT(FooDecl, NotNull()); 2472 2473 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2474 ASSERT_THAT(BarDecl, NotNull()); 2475 2476 const auto *FooVal = 2477 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2478 const auto *FooPointeeVal = 2479 cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc())); 2480 2481 const auto *BarVal = dyn_cast_or_null<IntegerValue>( 2482 Env.getValue(*BarDecl, SkipPast::None)); 2483 ASSERT_THAT(BarVal, NotNull()); 2484 2485 EXPECT_EQ(BarVal, FooPointeeVal); 2486 }); 2487 } 2488 2489 TEST(TransferTest, AggregateInitialization) { 2490 std::string BracesCode = R"( 2491 struct A { 2492 int Foo; 2493 }; 2494 2495 struct B { 2496 int Bar; 2497 A Baz; 2498 int Qux; 2499 }; 2500 2501 void target(int BarArg, int FooArg, int QuxArg) { 2502 B Quux{BarArg, {FooArg}, QuxArg}; 2503 /*[[p]]*/ 2504 } 2505 )"; 2506 std::string BraceEllisionCode = R"( 2507 struct A { 2508 int Foo; 2509 }; 2510 2511 struct B { 2512 int Bar; 2513 A Baz; 2514 int Qux; 2515 }; 2516 2517 void target(int BarArg, int FooArg, int QuxArg) { 2518 B Quux = {BarArg, FooArg, QuxArg}; 2519 /*[[p]]*/ 2520 } 2521 )"; 2522 for (const std::string &Code : {BracesCode, BraceEllisionCode}) { 2523 runDataflow( 2524 Code, [](llvm::ArrayRef< 2525 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2526 Results, 2527 ASTContext &ASTCtx) { 2528 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2529 const Environment &Env = Results[0].second.Env; 2530 2531 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2532 ASSERT_THAT(FooDecl, NotNull()); 2533 2534 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2535 ASSERT_THAT(BarDecl, NotNull()); 2536 2537 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2538 ASSERT_THAT(BazDecl, NotNull()); 2539 2540 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2541 ASSERT_THAT(QuxDecl, NotNull()); 2542 2543 const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg"); 2544 ASSERT_THAT(FooArgDecl, NotNull()); 2545 2546 const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg"); 2547 ASSERT_THAT(BarArgDecl, NotNull()); 2548 2549 const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg"); 2550 ASSERT_THAT(QuxArgDecl, NotNull()); 2551 2552 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 2553 ASSERT_THAT(QuuxDecl, NotNull()); 2554 2555 const auto *FooArgVal = 2556 cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None)); 2557 const auto *BarArgVal = 2558 cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None)); 2559 const auto *QuxArgVal = 2560 cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None)); 2561 2562 const auto *QuuxVal = 2563 cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None)); 2564 ASSERT_THAT(QuuxVal, NotNull()); 2565 2566 const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl)); 2567 ASSERT_THAT(BazVal, NotNull()); 2568 2569 EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal); 2570 EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal); 2571 EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal); 2572 }); 2573 } 2574 } 2575 2576 TEST(TransferTest, AssignToUnionMember) { 2577 std::string Code = R"( 2578 union A { 2579 int Foo; 2580 }; 2581 2582 void target(int Bar) { 2583 A Baz; 2584 Baz.Foo = Bar; 2585 // [[p]] 2586 } 2587 )"; 2588 runDataflow(Code, 2589 [](llvm::ArrayRef< 2590 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2591 Results, 2592 ASTContext &ASTCtx) { 2593 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2594 const Environment &Env = Results[0].second.Env; 2595 2596 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2597 ASSERT_THAT(BazDecl, NotNull()); 2598 ASSERT_TRUE(BazDecl->getType()->isUnionType()); 2599 2600 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>( 2601 Env.getStorageLocation(*BazDecl, SkipPast::None)); 2602 ASSERT_THAT(BazLoc, NotNull()); 2603 2604 // FIXME: Add support for union types. 2605 EXPECT_THAT(Env.getValue(*BazLoc), IsNull()); 2606 }); 2607 } 2608 2609 TEST(TransferTest, AssignFromBoolLiteral) { 2610 std::string Code = R"( 2611 void target() { 2612 bool Foo = true; 2613 bool Bar = false; 2614 // [[p]] 2615 } 2616 )"; 2617 runDataflow(Code, 2618 [](llvm::ArrayRef< 2619 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2620 Results, 2621 ASTContext &ASTCtx) { 2622 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2623 const Environment &Env = Results[0].second.Env; 2624 2625 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2626 ASSERT_THAT(FooDecl, NotNull()); 2627 2628 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2629 Env.getValue(*FooDecl, SkipPast::None)); 2630 ASSERT_THAT(FooVal, NotNull()); 2631 2632 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2633 ASSERT_THAT(BarDecl, NotNull()); 2634 2635 const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>( 2636 Env.getValue(*BarDecl, SkipPast::None)); 2637 ASSERT_THAT(BarVal, NotNull()); 2638 2639 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true)); 2640 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false)); 2641 }); 2642 } 2643 2644 TEST(TransferTest, AssignFromCompositeBoolExpression) { 2645 { 2646 std::string Code = R"( 2647 void target(bool Foo, bool Bar, bool Qux) { 2648 bool Baz = (Foo) && (Bar || Qux); 2649 // [[p]] 2650 } 2651 )"; 2652 runDataflow( 2653 Code, [](llvm::ArrayRef< 2654 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2655 Results, 2656 ASTContext &ASTCtx) { 2657 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2658 const Environment &Env = Results[0].second.Env; 2659 2660 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2661 ASSERT_THAT(FooDecl, NotNull()); 2662 2663 const auto *FooVal = dyn_cast_or_null<BoolValue>( 2664 Env.getValue(*FooDecl, SkipPast::None)); 2665 ASSERT_THAT(FooVal, NotNull()); 2666 2667 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2668 ASSERT_THAT(BarDecl, NotNull()); 2669 2670 const auto *BarVal = dyn_cast_or_null<BoolValue>( 2671 Env.getValue(*BarDecl, SkipPast::None)); 2672 ASSERT_THAT(BarVal, NotNull()); 2673 2674 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2675 ASSERT_THAT(QuxDecl, NotNull()); 2676 2677 const auto *QuxVal = dyn_cast_or_null<BoolValue>( 2678 Env.getValue(*QuxDecl, SkipPast::None)); 2679 ASSERT_THAT(QuxVal, NotNull()); 2680 2681 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2682 ASSERT_THAT(BazDecl, NotNull()); 2683 2684 const auto *BazVal = dyn_cast_or_null<ConjunctionValue>( 2685 Env.getValue(*BazDecl, SkipPast::None)); 2686 ASSERT_THAT(BazVal, NotNull()); 2687 EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal); 2688 2689 const auto *BazRightSubValVal = 2690 cast<DisjunctionValue>(&BazVal->getRightSubValue()); 2691 EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal); 2692 EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal); 2693 }); 2694 } 2695 2696 { 2697 std::string Code = R"( 2698 void target(bool Foo, bool Bar, bool Qux) { 2699 bool Baz = (Foo && Qux) || (Bar); 2700 // [[p]] 2701 } 2702 )"; 2703 runDataflow( 2704 Code, [](llvm::ArrayRef< 2705 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2706 Results, 2707 ASTContext &ASTCtx) { 2708 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2709 const Environment &Env = Results[0].second.Env; 2710 2711 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2712 ASSERT_THAT(FooDecl, NotNull()); 2713 2714 const auto *FooVal = dyn_cast_or_null<BoolValue>( 2715 Env.getValue(*FooDecl, SkipPast::None)); 2716 ASSERT_THAT(FooVal, NotNull()); 2717 2718 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2719 ASSERT_THAT(BarDecl, NotNull()); 2720 2721 const auto *BarVal = dyn_cast_or_null<BoolValue>( 2722 Env.getValue(*BarDecl, SkipPast::None)); 2723 ASSERT_THAT(BarVal, NotNull()); 2724 2725 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2726 ASSERT_THAT(QuxDecl, NotNull()); 2727 2728 const auto *QuxVal = dyn_cast_or_null<BoolValue>( 2729 Env.getValue(*QuxDecl, SkipPast::None)); 2730 ASSERT_THAT(QuxVal, NotNull()); 2731 2732 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2733 ASSERT_THAT(BazDecl, NotNull()); 2734 2735 const auto *BazVal = dyn_cast_or_null<DisjunctionValue>( 2736 Env.getValue(*BazDecl, SkipPast::None)); 2737 ASSERT_THAT(BazVal, NotNull()); 2738 2739 const auto *BazLeftSubValVal = 2740 cast<ConjunctionValue>(&BazVal->getLeftSubValue()); 2741 EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal); 2742 EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal); 2743 2744 EXPECT_EQ(&BazVal->getRightSubValue(), BarVal); 2745 }); 2746 } 2747 2748 { 2749 std::string Code = R"( 2750 void target(bool A, bool B, bool C, bool D) { 2751 bool Foo = ((A && B) && C) && D; 2752 // [[p]] 2753 } 2754 )"; 2755 runDataflow( 2756 Code, [](llvm::ArrayRef< 2757 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2758 Results, 2759 ASTContext &ASTCtx) { 2760 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2761 const Environment &Env = Results[0].second.Env; 2762 2763 const ValueDecl *ADecl = findValueDecl(ASTCtx, "A"); 2764 ASSERT_THAT(ADecl, NotNull()); 2765 2766 const auto *AVal = 2767 dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl, SkipPast::None)); 2768 ASSERT_THAT(AVal, NotNull()); 2769 2770 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 2771 ASSERT_THAT(BDecl, NotNull()); 2772 2773 const auto *BVal = 2774 dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl, SkipPast::None)); 2775 ASSERT_THAT(BVal, NotNull()); 2776 2777 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 2778 ASSERT_THAT(CDecl, NotNull()); 2779 2780 const auto *CVal = 2781 dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 2782 ASSERT_THAT(CVal, NotNull()); 2783 2784 const ValueDecl *DDecl = findValueDecl(ASTCtx, "D"); 2785 ASSERT_THAT(DDecl, NotNull()); 2786 2787 const auto *DVal = 2788 dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl, SkipPast::None)); 2789 ASSERT_THAT(DVal, NotNull()); 2790 2791 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2792 ASSERT_THAT(FooDecl, NotNull()); 2793 2794 const auto *FooVal = dyn_cast_or_null<ConjunctionValue>( 2795 Env.getValue(*FooDecl, SkipPast::None)); 2796 ASSERT_THAT(FooVal, NotNull()); 2797 2798 const auto &FooLeftSubVal = 2799 cast<ConjunctionValue>(FooVal->getLeftSubValue()); 2800 const auto &FooLeftLeftSubVal = 2801 cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue()); 2802 EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal); 2803 EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal); 2804 EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal); 2805 EXPECT_EQ(&FooVal->getRightSubValue(), DVal); 2806 }); 2807 } 2808 } 2809 2810 TEST(TransferTest, AssignFromBoolNegation) { 2811 std::string Code = R"( 2812 void target() { 2813 bool Foo = true; 2814 bool Bar = !(Foo); 2815 // [[p]] 2816 } 2817 )"; 2818 runDataflow(Code, 2819 [](llvm::ArrayRef< 2820 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2821 Results, 2822 ASTContext &ASTCtx) { 2823 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2824 const Environment &Env = Results[0].second.Env; 2825 2826 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2827 ASSERT_THAT(FooDecl, NotNull()); 2828 2829 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2830 Env.getValue(*FooDecl, SkipPast::None)); 2831 ASSERT_THAT(FooVal, NotNull()); 2832 2833 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2834 ASSERT_THAT(BarDecl, NotNull()); 2835 2836 const auto *BarVal = dyn_cast_or_null<NegationValue>( 2837 Env.getValue(*BarDecl, SkipPast::None)); 2838 ASSERT_THAT(BarVal, NotNull()); 2839 2840 EXPECT_EQ(&BarVal->getSubVal(), FooVal); 2841 }); 2842 } 2843 2844 TEST(TransferTest, BuiltinExpect) { 2845 std::string Code = R"( 2846 void target(long Foo) { 2847 long Bar = __builtin_expect(Foo, true); 2848 /*[[p]]*/ 2849 } 2850 )"; 2851 runDataflow(Code, 2852 [](llvm::ArrayRef< 2853 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2854 Results, 2855 ASTContext &ASTCtx) { 2856 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2857 const auto &Env = Results[0].second.Env; 2858 2859 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2860 ASSERT_THAT(FooDecl, NotNull()); 2861 2862 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2863 ASSERT_THAT(BarDecl, NotNull()); 2864 2865 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2866 Env.getValue(*BarDecl, SkipPast::None)); 2867 }); 2868 } 2869 2870 // `__builtin_expect` takes and returns a `long` argument, so other types 2871 // involve casts. This verifies that we identify the input and output in that 2872 // case. 2873 TEST(TransferTest, BuiltinExpectBoolArg) { 2874 std::string Code = R"( 2875 void target(bool Foo) { 2876 bool Bar = __builtin_expect(Foo, true); 2877 /*[[p]]*/ 2878 } 2879 )"; 2880 runDataflow(Code, 2881 [](llvm::ArrayRef< 2882 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2883 Results, 2884 ASTContext &ASTCtx) { 2885 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2886 const auto &Env = Results[0].second.Env; 2887 2888 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2889 ASSERT_THAT(FooDecl, NotNull()); 2890 2891 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2892 ASSERT_THAT(BarDecl, NotNull()); 2893 2894 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2895 Env.getValue(*BarDecl, SkipPast::None)); 2896 }); 2897 } 2898 2899 TEST(TransferTest, BuiltinUnreachable) { 2900 std::string Code = R"( 2901 void target(bool Foo) { 2902 bool Bar = false; 2903 if (Foo) 2904 Bar = Foo; 2905 else 2906 __builtin_unreachable(); 2907 (void)0; 2908 /*[[p]]*/ 2909 } 2910 )"; 2911 runDataflow(Code, 2912 [](llvm::ArrayRef< 2913 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2914 Results, 2915 ASTContext &ASTCtx) { 2916 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2917 const auto &Env = Results[0].second.Env; 2918 2919 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2920 ASSERT_THAT(FooDecl, NotNull()); 2921 2922 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2923 ASSERT_THAT(BarDecl, NotNull()); 2924 2925 // `__builtin_unreachable` promises that the code is 2926 // unreachable, so the compiler treats the "then" branch as the 2927 // only possible predecessor of this statement. 2928 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2929 Env.getValue(*BarDecl, SkipPast::None)); 2930 }); 2931 } 2932 2933 TEST(TransferTest, BuiltinTrap) { 2934 std::string Code = R"( 2935 void target(bool Foo) { 2936 bool Bar = false; 2937 if (Foo) 2938 Bar = Foo; 2939 else 2940 __builtin_trap(); 2941 (void)0; 2942 /*[[p]]*/ 2943 } 2944 )"; 2945 runDataflow(Code, 2946 [](llvm::ArrayRef< 2947 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2948 Results, 2949 ASTContext &ASTCtx) { 2950 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2951 const auto &Env = Results[0].second.Env; 2952 2953 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2954 ASSERT_THAT(FooDecl, NotNull()); 2955 2956 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2957 ASSERT_THAT(BarDecl, NotNull()); 2958 2959 // `__builtin_trap` ensures program termination, so only the 2960 // "then" branch is a predecessor of this statement. 2961 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2962 Env.getValue(*BarDecl, SkipPast::None)); 2963 }); 2964 } 2965 2966 TEST(TransferTest, BuiltinDebugTrap) { 2967 std::string Code = R"( 2968 void target(bool Foo) { 2969 bool Bar = false; 2970 if (Foo) 2971 Bar = Foo; 2972 else 2973 __builtin_debugtrap(); 2974 (void)0; 2975 /*[[p]]*/ 2976 } 2977 )"; 2978 runDataflow(Code, 2979 [](llvm::ArrayRef< 2980 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2981 Results, 2982 ASTContext &ASTCtx) { 2983 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2984 const auto &Env = Results[0].second.Env; 2985 2986 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2987 ASSERT_THAT(FooDecl, NotNull()); 2988 2989 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2990 ASSERT_THAT(BarDecl, NotNull()); 2991 2992 // `__builtin_debugtrap` doesn't ensure program termination. 2993 EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None), 2994 Env.getValue(*BarDecl, SkipPast::None)); 2995 }); 2996 } 2997 2998 TEST(TransferTest, StaticIntSingleVarDecl) { 2999 std::string Code = R"( 3000 void target() { 3001 static int Foo; 3002 // [[p]] 3003 } 3004 )"; 3005 runDataflow(Code, 3006 [](llvm::ArrayRef< 3007 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3008 Results, 3009 ASTContext &ASTCtx) { 3010 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3011 const Environment &Env = Results[0].second.Env; 3012 3013 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3014 ASSERT_THAT(FooDecl, NotNull()); 3015 3016 const StorageLocation *FooLoc = 3017 Env.getStorageLocation(*FooDecl, SkipPast::None); 3018 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3019 3020 const Value *FooVal = Env.getValue(*FooLoc); 3021 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3022 }); 3023 } 3024 3025 TEST(TransferTest, StaticIntGroupVarDecl) { 3026 std::string Code = R"( 3027 void target() { 3028 static int Foo, Bar; 3029 (void)0; 3030 // [[p]] 3031 } 3032 )"; 3033 runDataflow(Code, 3034 [](llvm::ArrayRef< 3035 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3036 Results, 3037 ASTContext &ASTCtx) { 3038 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3039 const Environment &Env = Results[0].second.Env; 3040 3041 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3042 ASSERT_THAT(FooDecl, NotNull()); 3043 3044 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3045 ASSERT_THAT(BarDecl, NotNull()); 3046 3047 const StorageLocation *FooLoc = 3048 Env.getStorageLocation(*FooDecl, SkipPast::None); 3049 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3050 3051 const StorageLocation *BarLoc = 3052 Env.getStorageLocation(*BarDecl, SkipPast::None); 3053 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 3054 3055 const Value *FooVal = Env.getValue(*FooLoc); 3056 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3057 3058 const Value *BarVal = Env.getValue(*BarLoc); 3059 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 3060 3061 EXPECT_NE(FooVal, BarVal); 3062 }); 3063 } 3064 3065 TEST(TransferTest, GlobalIntVarDecl) { 3066 std::string Code = R"( 3067 static int Foo; 3068 3069 void target() { 3070 int Bar = Foo; 3071 int Baz = Foo; 3072 // [[p]] 3073 } 3074 )"; 3075 runDataflow(Code, 3076 [](llvm::ArrayRef< 3077 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3078 Results, 3079 ASTContext &ASTCtx) { 3080 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3081 const Environment &Env = Results[0].second.Env; 3082 3083 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3084 ASSERT_THAT(BarDecl, NotNull()); 3085 3086 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3087 ASSERT_THAT(BazDecl, NotNull()); 3088 3089 const Value *BarVal = 3090 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3091 const Value *BazVal = 3092 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 3093 EXPECT_EQ(BarVal, BazVal); 3094 }); 3095 } 3096 3097 TEST(TransferTest, StaticMemberIntVarDecl) { 3098 std::string Code = R"( 3099 struct A { 3100 static int Foo; 3101 }; 3102 3103 void target(A a) { 3104 int Bar = a.Foo; 3105 int Baz = a.Foo; 3106 // [[p]] 3107 } 3108 )"; 3109 runDataflow(Code, 3110 [](llvm::ArrayRef< 3111 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3112 Results, 3113 ASTContext &ASTCtx) { 3114 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3115 const Environment &Env = Results[0].second.Env; 3116 3117 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3118 ASSERT_THAT(BarDecl, NotNull()); 3119 3120 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3121 ASSERT_THAT(BazDecl, NotNull()); 3122 3123 const Value *BarVal = 3124 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3125 const Value *BazVal = 3126 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 3127 EXPECT_EQ(BarVal, BazVal); 3128 }); 3129 } 3130 3131 TEST(TransferTest, StaticMemberRefVarDecl) { 3132 std::string Code = R"( 3133 struct A { 3134 static int &Foo; 3135 }; 3136 3137 void target(A a) { 3138 int Bar = a.Foo; 3139 int Baz = a.Foo; 3140 // [[p]] 3141 } 3142 )"; 3143 runDataflow(Code, 3144 [](llvm::ArrayRef< 3145 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3146 Results, 3147 ASTContext &ASTCtx) { 3148 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3149 const Environment &Env = Results[0].second.Env; 3150 3151 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3152 ASSERT_THAT(BarDecl, NotNull()); 3153 3154 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3155 ASSERT_THAT(BazDecl, NotNull()); 3156 3157 const Value *BarVal = 3158 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3159 const Value *BazVal = 3160 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 3161 EXPECT_EQ(BarVal, BazVal); 3162 }); 3163 } 3164 3165 TEST(TransferTest, AssignMemberBeforeCopy) { 3166 std::string Code = R"( 3167 struct A { 3168 int Foo; 3169 }; 3170 3171 void target() { 3172 A A1; 3173 A A2; 3174 int Bar; 3175 A1.Foo = Bar; 3176 A2 = A1; 3177 // [[p]] 3178 } 3179 )"; 3180 runDataflow(Code, 3181 [](llvm::ArrayRef< 3182 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3183 Results, 3184 ASTContext &ASTCtx) { 3185 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3186 const Environment &Env = Results[0].second.Env; 3187 3188 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3189 ASSERT_THAT(FooDecl, NotNull()); 3190 3191 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3192 ASSERT_THAT(BarDecl, NotNull()); 3193 3194 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); 3195 ASSERT_THAT(A1Decl, NotNull()); 3196 3197 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); 3198 ASSERT_THAT(A2Decl, NotNull()); 3199 3200 const auto *BarVal = 3201 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3202 3203 const auto *A2Val = 3204 cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None)); 3205 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal); 3206 }); 3207 } 3208 3209 TEST(TransferTest, BooleanEquality) { 3210 std::string Code = R"( 3211 void target(bool Bar) { 3212 bool Foo = true; 3213 if (Bar == Foo) { 3214 (void)0; 3215 /*[[p-then]]*/ 3216 } else { 3217 (void)0; 3218 /*[[p-else]]*/ 3219 } 3220 } 3221 )"; 3222 runDataflow( 3223 Code, [](llvm::ArrayRef< 3224 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3225 Results, 3226 ASTContext &ASTCtx) { 3227 ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _))); 3228 const Environment &EnvElse = Results[0].second.Env; 3229 const Environment &EnvThen = Results[1].second.Env; 3230 3231 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3232 ASSERT_THAT(BarDecl, NotNull()); 3233 3234 auto &BarValThen = 3235 *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None)); 3236 EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen)); 3237 3238 auto &BarValElse = 3239 *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None)); 3240 EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse)); 3241 }); 3242 } 3243 3244 TEST(TransferTest, BooleanInequality) { 3245 std::string Code = R"( 3246 void target(bool Bar) { 3247 bool Foo = true; 3248 if (Bar != Foo) { 3249 (void)0; 3250 /*[[p-then]]*/ 3251 } else { 3252 (void)0; 3253 /*[[p-else]]*/ 3254 } 3255 } 3256 )"; 3257 runDataflow( 3258 Code, [](llvm::ArrayRef< 3259 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3260 Results, 3261 ASTContext &ASTCtx) { 3262 ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _))); 3263 const Environment &EnvElse = Results[0].second.Env; 3264 const Environment &EnvThen = Results[1].second.Env; 3265 3266 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3267 ASSERT_THAT(BarDecl, NotNull()); 3268 3269 auto &BarValThen = 3270 *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None)); 3271 EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen)); 3272 3273 auto &BarValElse = 3274 *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None)); 3275 EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse)); 3276 }); 3277 } 3278 3279 TEST(TransferTest, CorrelatedBranches) { 3280 std::string Code = R"( 3281 void target(bool B, bool C) { 3282 if (B) { 3283 return; 3284 } 3285 (void)0; 3286 /*[[p0]]*/ 3287 if (C) { 3288 B = true; 3289 /*[[p1]]*/ 3290 } 3291 if (B) { 3292 (void)0; 3293 /*[[p2]]*/ 3294 } 3295 } 3296 )"; 3297 runDataflow( 3298 Code, [](llvm::ArrayRef< 3299 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3300 Results, 3301 ASTContext &ASTCtx) { 3302 ASSERT_THAT(Results, SizeIs(3)); 3303 3304 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3305 ASSERT_THAT(CDecl, NotNull()); 3306 3307 { 3308 ASSERT_THAT(Results[2], Pair("p0", _)); 3309 const Environment &Env = Results[2].second.Env; 3310 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3311 ASSERT_THAT(BDecl, NotNull()); 3312 auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None)); 3313 3314 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal))); 3315 } 3316 3317 { 3318 ASSERT_THAT(Results[1], Pair("p1", _)); 3319 const Environment &Env = Results[1].second.Env; 3320 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 3321 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3322 } 3323 3324 { 3325 ASSERT_THAT(Results[0], Pair("p2", _)); 3326 const Environment &Env = Results[0].second.Env; 3327 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 3328 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3329 } 3330 }); 3331 } 3332 3333 TEST(TransferTest, LoopWithAssignmentConverges) { 3334 std::string Code = R"( 3335 3336 bool &foo(); 3337 3338 void target() { 3339 do { 3340 bool Bar = foo(); 3341 if (Bar) break; 3342 (void)Bar; 3343 /*[[p]]*/ 3344 } while (true); 3345 } 3346 )"; 3347 // The key property that we are verifying is implicit in `runDataflow` -- 3348 // namely, that the analysis succeeds, rather than hitting the maximum number 3349 // of iterations. 3350 runDataflow( 3351 Code, [](llvm::ArrayRef< 3352 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3353 Results, 3354 ASTContext &ASTCtx) { 3355 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3356 const Environment &Env = Results[0].second.Env; 3357 3358 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3359 ASSERT_THAT(BarDecl, NotNull()); 3360 3361 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 3362 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3363 }); 3364 } 3365 3366 TEST(TransferTest, LoopWithReferenceAssignmentConverges) { 3367 std::string Code = R"( 3368 3369 bool &foo(); 3370 3371 void target() { 3372 do { 3373 bool& Bar = foo(); 3374 if (Bar) break; 3375 (void)Bar; 3376 /*[[p]]*/ 3377 } while (true); 3378 } 3379 )"; 3380 // The key property that we are verifying is implicit in `runDataflow` -- 3381 // namely, that the analysis succeeds, rather than hitting the maximum number 3382 // of iterations. 3383 runDataflow( 3384 Code, [](llvm::ArrayRef< 3385 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3386 Results, 3387 ASTContext &ASTCtx) { 3388 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3389 const Environment &Env = Results[0].second.Env; 3390 3391 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3392 ASSERT_THAT(BarDecl, NotNull()); 3393 3394 auto &BarVal = 3395 *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference)); 3396 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3397 }); 3398 } 3399 3400 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) { 3401 std::string Code = R"( 3402 struct Lookup { 3403 int x; 3404 }; 3405 3406 void target(Lookup val, bool b) { 3407 const Lookup* l = nullptr; 3408 while (b) { 3409 l = &val; 3410 /*[[p-inner]]*/ 3411 } 3412 (void)0; 3413 /*[[p-outer]]*/ 3414 } 3415 )"; 3416 // The key property that we are verifying is implicit in `runDataflow` -- 3417 // namely, that the analysis succeeds, rather than hitting the maximum number 3418 // of iterations. 3419 runDataflow( 3420 Code, [](llvm::ArrayRef< 3421 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3422 Results, 3423 ASTContext &ASTCtx) { 3424 ASSERT_THAT(Results, 3425 ElementsAre(Pair("p-outer", _), Pair("p-inner", _))); 3426 const Environment &OuterEnv = Results[0].second.Env; 3427 const Environment &InnerEnv = Results[1].second.Env; 3428 3429 const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val"); 3430 ASSERT_THAT(ValDecl, NotNull()); 3431 3432 const ValueDecl *LDecl = findValueDecl(ASTCtx, "l"); 3433 ASSERT_THAT(LDecl, NotNull()); 3434 3435 // Inner. 3436 auto *LVal = 3437 dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl, SkipPast::None)); 3438 ASSERT_THAT(LVal, NotNull()); 3439 3440 EXPECT_EQ(&LVal->getPointeeLoc(), 3441 InnerEnv.getStorageLocation(*ValDecl, SkipPast::Reference)); 3442 3443 // Outer. 3444 LVal = 3445 dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl, SkipPast::None)); 3446 ASSERT_THAT(LVal, NotNull()); 3447 3448 // The loop body may not have been executed, so we should not conclude 3449 // that `l` points to `val`. 3450 EXPECT_NE(&LVal->getPointeeLoc(), 3451 OuterEnv.getStorageLocation(*ValDecl, SkipPast::Reference)); 3452 }); 3453 } 3454 3455 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { 3456 std::string Code = R"( 3457 union Union { 3458 int A; 3459 float B; 3460 }; 3461 3462 void foo() { 3463 Union A; 3464 Union B; 3465 A = B; 3466 } 3467 )"; 3468 // This is a crash regression test when calling the transfer function on a 3469 // `CXXThisExpr` that refers to a union. 3470 runDataflow( 3471 Code, 3472 [](llvm::ArrayRef< 3473 std::pair<std::string, DataflowAnalysisState<NoopLattice>>>, 3474 ASTContext &) {}, 3475 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator="); 3476 } 3477 3478 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) { 3479 std::string Code = R"( 3480 struct A { 3481 int Foo; 3482 int Bar; 3483 }; 3484 3485 void target() { 3486 int Qux; 3487 A Baz; 3488 Baz.Foo = Qux; 3489 auto &FooRef = Baz.Foo; 3490 auto &BarRef = Baz.Bar; 3491 auto &[BoundFooRef, BoundBarRef] = Baz; 3492 // [[p]] 3493 } 3494 )"; 3495 runDataflow( 3496 Code, [](llvm::ArrayRef< 3497 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3498 Results, 3499 ASTContext &ASTCtx) { 3500 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3501 const Environment &Env = Results[0].second.Env; 3502 3503 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3504 ASSERT_THAT(FooRefDecl, NotNull()); 3505 3506 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3507 ASSERT_THAT(BarRefDecl, NotNull()); 3508 3509 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3510 ASSERT_THAT(QuxDecl, NotNull()); 3511 3512 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3513 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3514 3515 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3516 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3517 3518 const StorageLocation *FooRefLoc = 3519 Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); 3520 ASSERT_THAT(FooRefLoc, NotNull()); 3521 3522 const StorageLocation *BarRefLoc = 3523 Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); 3524 ASSERT_THAT(BarRefLoc, NotNull()); 3525 3526 const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); 3527 ASSERT_THAT(QuxVal, NotNull()); 3528 3529 const StorageLocation *BoundFooRefLoc = 3530 Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference); 3531 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3532 3533 const StorageLocation *BoundBarRefLoc = 3534 Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference); 3535 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3536 3537 EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal); 3538 }); 3539 } 3540 3541 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) { 3542 std::string Code = R"( 3543 struct A { 3544 int &Foo; 3545 int &Bar; 3546 }; 3547 3548 void target(A Baz) { 3549 int Qux; 3550 Baz.Foo = Qux; 3551 auto &FooRef = Baz.Foo; 3552 auto &BarRef = Baz.Bar; 3553 auto &[BoundFooRef, BoundBarRef] = Baz; 3554 // [[p]] 3555 } 3556 )"; 3557 runDataflow( 3558 Code, [](llvm::ArrayRef< 3559 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3560 Results, 3561 ASTContext &ASTCtx) { 3562 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3563 const Environment &Env = Results[0].second.Env; 3564 3565 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3566 ASSERT_THAT(FooRefDecl, NotNull()); 3567 3568 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3569 ASSERT_THAT(BarRefDecl, NotNull()); 3570 3571 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3572 ASSERT_THAT(QuxDecl, NotNull()); 3573 3574 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3575 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3576 3577 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3578 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3579 3580 const StorageLocation *FooRefLoc = 3581 Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); 3582 ASSERT_THAT(FooRefLoc, NotNull()); 3583 3584 const StorageLocation *BarRefLoc = 3585 Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); 3586 ASSERT_THAT(BarRefLoc, NotNull()); 3587 3588 const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); 3589 ASSERT_THAT(QuxVal, NotNull()); 3590 3591 const StorageLocation *BoundFooRefLoc = 3592 Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference); 3593 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3594 3595 const StorageLocation *BoundBarRefLoc = 3596 Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference); 3597 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3598 3599 EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal); 3600 }); 3601 } 3602 3603 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) { 3604 std::string Code = R"( 3605 struct A { 3606 int Foo; 3607 int Bar; 3608 }; 3609 3610 void target() { 3611 int Qux; 3612 A Baz; 3613 Baz.Foo = Qux; 3614 auto &FooRef = Baz.Foo; 3615 auto &BarRef = Baz.Bar; 3616 auto [BoundFoo, BoundBar] = Baz; 3617 // [[p]] 3618 } 3619 )"; 3620 runDataflow( 3621 Code, [](llvm::ArrayRef< 3622 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3623 Results, 3624 ASTContext &ASTCtx) { 3625 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3626 const Environment &Env = Results[0].second.Env; 3627 3628 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3629 ASSERT_THAT(FooRefDecl, NotNull()); 3630 3631 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3632 ASSERT_THAT(BarRefDecl, NotNull()); 3633 3634 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 3635 ASSERT_THAT(BoundFooDecl, NotNull()); 3636 3637 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 3638 ASSERT_THAT(BoundBarDecl, NotNull()); 3639 3640 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3641 ASSERT_THAT(QuxDecl, NotNull()); 3642 3643 const StorageLocation *FooRefLoc = 3644 Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); 3645 ASSERT_THAT(FooRefLoc, NotNull()); 3646 3647 const StorageLocation *BarRefLoc = 3648 Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); 3649 ASSERT_THAT(BarRefLoc, NotNull()); 3650 3651 const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); 3652 ASSERT_THAT(QuxVal, NotNull()); 3653 3654 const StorageLocation *BoundFooLoc = 3655 Env.getStorageLocation(*BoundFooDecl, SkipPast::Reference); 3656 EXPECT_NE(BoundFooLoc, FooRefLoc); 3657 3658 const StorageLocation *BoundBarLoc = 3659 Env.getStorageLocation(*BoundBarDecl, SkipPast::Reference); 3660 EXPECT_NE(BoundBarLoc, BarRefLoc); 3661 3662 EXPECT_EQ(Env.getValue(*BoundFooDecl, SkipPast::Reference), QuxVal); 3663 }); 3664 } 3665 3666 TEST(TransferTest, BinaryOperatorComma) { 3667 std::string Code = R"( 3668 void target(int Foo, int Bar) { 3669 int &Baz = (Foo, Bar); 3670 // [[p]] 3671 } 3672 )"; 3673 runDataflow(Code, 3674 [](llvm::ArrayRef< 3675 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3676 Results, 3677 ASTContext &ASTCtx) { 3678 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3679 const Environment &Env = Results[0].second.Env; 3680 3681 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3682 ASSERT_THAT(BarDecl, NotNull()); 3683 3684 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3685 ASSERT_THAT(BazDecl, NotNull()); 3686 3687 const StorageLocation *BarLoc = 3688 Env.getStorageLocation(*BarDecl, SkipPast::Reference); 3689 ASSERT_THAT(BarLoc, NotNull()); 3690 3691 const StorageLocation *BazLoc = 3692 Env.getStorageLocation(*BazDecl, SkipPast::Reference); 3693 EXPECT_EQ(BazLoc, BarLoc); 3694 }); 3695 } 3696 3697 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) { 3698 std::string Code = R"( 3699 void target(bool Foo) { 3700 if (Foo) { 3701 (void)0; 3702 // [[if_then]] 3703 } else { 3704 (void)0; 3705 // [[if_else]] 3706 } 3707 } 3708 )"; 3709 runDataflow( 3710 Code, [](llvm::ArrayRef< 3711 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3712 Results, 3713 ASTContext &ASTCtx) { 3714 ASSERT_THAT(Results, 3715 ElementsAre(Pair("if_else", _), Pair("if_then", _))); 3716 const Environment &ThenEnv = Results[1].second.Env; 3717 const Environment &ElseEnv = Results[0].second.Env; 3718 3719 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3720 ASSERT_THAT(FooDecl, NotNull()); 3721 3722 BoolValue &ThenFooVal = 3723 *cast<BoolValue>(ThenEnv.getValue(*FooDecl, SkipPast::None)); 3724 EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal)); 3725 3726 BoolValue &ElseFooVal = 3727 *cast<BoolValue>(ElseEnv.getValue(*FooDecl, SkipPast::None)); 3728 EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal))); 3729 }); 3730 } 3731 3732 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) { 3733 std::string Code = R"( 3734 void target(bool Foo) { 3735 while (Foo) { 3736 (void)0; 3737 // [[loop_body]] 3738 } 3739 (void)0; 3740 // [[after_loop]] 3741 } 3742 )"; 3743 runDataflow( 3744 Code, [](llvm::ArrayRef< 3745 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3746 Results, 3747 ASTContext &ASTCtx) { 3748 ASSERT_THAT(Results, 3749 ElementsAre(Pair("after_loop", _), Pair("loop_body", _))); 3750 const Environment &LoopBodyEnv = Results[1].second.Env; 3751 const Environment &AfterLoopEnv = Results[0].second.Env; 3752 3753 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3754 ASSERT_THAT(FooDecl, NotNull()); 3755 3756 BoolValue &LoopBodyFooVal = 3757 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 3758 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 3759 3760 BoolValue &AfterLoopFooVal = 3761 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None)); 3762 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 3763 AfterLoopEnv.makeNot(AfterLoopFooVal))); 3764 }); 3765 } 3766 3767 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) { 3768 std::string Code = R"( 3769 void target(bool Foo) { 3770 bool Bar = true; 3771 do { 3772 (void)0; 3773 // [[loop_body]] 3774 Bar = false; 3775 } while (Foo); 3776 (void)0; 3777 // [[after_loop]] 3778 } 3779 )"; 3780 runDataflow( 3781 Code, [](llvm::ArrayRef< 3782 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3783 Results, 3784 ASTContext &ASTCtx) { 3785 ASSERT_THAT(Results, 3786 ElementsAre(Pair("after_loop", _), Pair("loop_body", _))); 3787 const Environment &LoopBodyEnv = Results[1].second.Env; 3788 const Environment &AfterLoopEnv = Results[0].second.Env; 3789 3790 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3791 ASSERT_THAT(FooDecl, NotNull()); 3792 3793 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3794 ASSERT_THAT(BarDecl, NotNull()); 3795 3796 BoolValue &LoopBodyFooVal = 3797 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 3798 BoolValue &LoopBodyBarVal = 3799 *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl, SkipPast::None)); 3800 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies( 3801 LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal))); 3802 3803 BoolValue &AfterLoopFooVal = 3804 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None)); 3805 BoolValue &AfterLoopBarVal = 3806 *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl, SkipPast::None)); 3807 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 3808 AfterLoopEnv.makeNot(AfterLoopFooVal))); 3809 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 3810 AfterLoopEnv.makeNot(AfterLoopBarVal))); 3811 }); 3812 } 3813 3814 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) { 3815 std::string Code = R"( 3816 void target(bool Foo) { 3817 for (; Foo;) { 3818 (void)0; 3819 // [[loop_body]] 3820 } 3821 (void)0; 3822 // [[after_loop]] 3823 } 3824 )"; 3825 runDataflow( 3826 Code, [](llvm::ArrayRef< 3827 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3828 Results, 3829 ASTContext &ASTCtx) { 3830 ASSERT_THAT(Results, 3831 ElementsAre(Pair("after_loop", _), Pair("loop_body", _))); 3832 const Environment &LoopBodyEnv = Results[1].second.Env; 3833 const Environment &AfterLoopEnv = Results[0].second.Env; 3834 3835 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3836 ASSERT_THAT(FooDecl, NotNull()); 3837 3838 BoolValue &LoopBodyFooVal = 3839 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 3840 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 3841 3842 BoolValue &AfterLoopFooVal = 3843 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None)); 3844 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 3845 AfterLoopEnv.makeNot(AfterLoopFooVal))); 3846 }); 3847 } 3848 3849 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) { 3850 std::string Code = R"( 3851 void target(bool Foo) { 3852 for (;;) { 3853 (void)0; 3854 // [[loop_body]] 3855 } 3856 } 3857 )"; 3858 runDataflow( 3859 Code, [](llvm::ArrayRef< 3860 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3861 Results, 3862 ASTContext &ASTCtx) { 3863 ASSERT_THAT(Results, ElementsAre(Pair("loop_body", _))); 3864 const Environment &LoopBodyEnv = Results[0].second.Env; 3865 3866 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3867 ASSERT_THAT(FooDecl, NotNull()); 3868 3869 BoolValue &LoopBodyFooVal = 3870 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 3871 EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 3872 }); 3873 } 3874 3875 TEST(TransferTest, ContextSensitiveOptionDisabled) { 3876 std::string Code = R"( 3877 bool GiveBool(); 3878 void SetBool(bool &Var) { Var = true; } 3879 3880 void target() { 3881 bool Foo = GiveBool(); 3882 SetBool(Foo); 3883 // [[p]] 3884 } 3885 )"; 3886 runDataflow(Code, 3887 [](llvm::ArrayRef< 3888 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3889 Results, 3890 ASTContext &ASTCtx) { 3891 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3892 const Environment &Env = Results[0].second.Env; 3893 3894 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3895 ASSERT_THAT(FooDecl, NotNull()); 3896 3897 auto &FooVal = 3898 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 3899 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 3900 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 3901 }, 3902 {TransferOptions{/*.ContextSensitiveOpts=*/llvm::None}}); 3903 } 3904 3905 TEST(TransferTest, ContextSensitiveSetTrue) { 3906 std::string Code = R"( 3907 bool GiveBool(); 3908 void SetBool(bool &Var) { Var = true; } 3909 3910 void target() { 3911 bool Foo = GiveBool(); 3912 SetBool(Foo); 3913 // [[p]] 3914 } 3915 )"; 3916 runDataflow(Code, 3917 [](llvm::ArrayRef< 3918 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3919 Results, 3920 ASTContext &ASTCtx) { 3921 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3922 const Environment &Env = Results[0].second.Env; 3923 3924 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3925 ASSERT_THAT(FooDecl, NotNull()); 3926 3927 auto &FooVal = 3928 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 3929 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 3930 }, 3931 {TransferOptions{ContextSensitiveOptions{}}}); 3932 } 3933 3934 TEST(TransferTest, ContextSensitiveSetFalse) { 3935 std::string Code = R"( 3936 bool GiveBool(); 3937 void SetBool(bool &Var) { Var = false; } 3938 3939 void target() { 3940 bool Foo = GiveBool(); 3941 SetBool(Foo); 3942 // [[p]] 3943 } 3944 )"; 3945 runDataflow(Code, 3946 [](llvm::ArrayRef< 3947 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3948 Results, 3949 ASTContext &ASTCtx) { 3950 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3951 const Environment &Env = Results[0].second.Env; 3952 3953 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3954 ASSERT_THAT(FooDecl, NotNull()); 3955 3956 auto &FooVal = 3957 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 3958 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal))); 3959 }, 3960 {TransferOptions{ContextSensitiveOptions{}}}); 3961 } 3962 3963 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) { 3964 std::string Code = R"( 3965 bool GiveBool(); 3966 void SetBool(bool &Var, bool Val) { Var = Val; } 3967 3968 void target() { 3969 bool Foo = GiveBool(); 3970 bool Bar = GiveBool(); 3971 SetBool(Foo, true); 3972 SetBool(Bar, false); 3973 // [[p]] 3974 } 3975 )"; 3976 runDataflow(Code, 3977 [](llvm::ArrayRef< 3978 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 3979 Results, 3980 ASTContext &ASTCtx) { 3981 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 3982 const Environment &Env = Results[0].second.Env; 3983 3984 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3985 ASSERT_THAT(FooDecl, NotNull()); 3986 3987 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3988 ASSERT_THAT(BarDecl, NotNull()); 3989 3990 auto &FooVal = 3991 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 3992 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 3993 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 3994 3995 auto &BarVal = 3996 *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 3997 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 3998 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3999 }, 4000 {TransferOptions{ContextSensitiveOptions{}}}); 4001 } 4002 4003 TEST(TransferTest, ContextSensitiveSetTwoLayers) { 4004 std::string Code = R"( 4005 bool GiveBool(); 4006 void SetBool1(bool &Var) { Var = true; } 4007 void SetBool2(bool &Var) { SetBool1(Var); } 4008 4009 void target() { 4010 bool Foo = GiveBool(); 4011 SetBool2(Foo); 4012 // [[p]] 4013 } 4014 )"; 4015 runDataflow(Code, 4016 [](llvm::ArrayRef< 4017 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4018 Results, 4019 ASTContext &ASTCtx) { 4020 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4021 const Environment &Env = Results[0].second.Env; 4022 4023 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4024 ASSERT_THAT(FooDecl, NotNull()); 4025 4026 auto &FooVal = 4027 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4028 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4029 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4030 }, 4031 {TransferOptions{ContextSensitiveOptions{}}}); 4032 } 4033 4034 TEST(TransferTest, ContextSensitiveSetMultipleLines) { 4035 std::string Code = R"( 4036 void SetBools(bool &Var1, bool &Var2) { 4037 Var1 = true; 4038 Var2 = false; 4039 } 4040 4041 void target() { 4042 bool Foo = false; 4043 bool Bar = true; 4044 SetBools(Foo, Bar); 4045 // [[p]] 4046 } 4047 )"; 4048 runDataflow(Code, 4049 [](llvm::ArrayRef< 4050 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4051 Results, 4052 ASTContext &ASTCtx) { 4053 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4054 const Environment &Env = Results[0].second.Env; 4055 4056 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4057 ASSERT_THAT(FooDecl, NotNull()); 4058 4059 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4060 ASSERT_THAT(BarDecl, NotNull()); 4061 4062 auto &FooVal = 4063 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4064 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4065 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4066 4067 auto &BarVal = 4068 *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 4069 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4070 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4071 }, 4072 {TransferOptions{ContextSensitiveOptions{}}}); 4073 } 4074 4075 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) { 4076 std::string Code = R"( 4077 void IfCond(bool Cond, bool &Then, bool &Else) { 4078 if (Cond) { 4079 Then = true; 4080 } else { 4081 Else = true; 4082 } 4083 } 4084 4085 void target() { 4086 bool Foo = false; 4087 bool Bar = false; 4088 bool Baz = false; 4089 IfCond(Foo, Bar, Baz); 4090 // [[p]] 4091 } 4092 )"; 4093 runDataflow(Code, 4094 [](llvm::ArrayRef< 4095 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4096 Results, 4097 ASTContext &ASTCtx) { 4098 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4099 const Environment &Env = Results[0].second.Env; 4100 4101 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4102 ASSERT_THAT(BarDecl, NotNull()); 4103 4104 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4105 ASSERT_THAT(BazDecl, NotNull()); 4106 4107 auto &BarVal = 4108 *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 4109 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4110 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4111 4112 auto &BazVal = 4113 *cast<BoolValue>(Env.getValue(*BazDecl, SkipPast::None)); 4114 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 4115 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal))); 4116 }, 4117 {TransferOptions{ContextSensitiveOptions{}}}); 4118 } 4119 4120 TEST(TransferTest, ContextSensitiveReturnVoid) { 4121 std::string Code = R"( 4122 void Noop() { return; } 4123 4124 void target() { 4125 Noop(); 4126 // [[p]] 4127 } 4128 )"; 4129 runDataflow(Code, 4130 [](llvm::ArrayRef< 4131 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4132 Results, 4133 ASTContext &ASTCtx) { 4134 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4135 // This just tests that the analysis doesn't crash. 4136 }, 4137 {TransferOptions{ContextSensitiveOptions{}}}); 4138 } 4139 4140 TEST(TransferTest, ContextSensitiveReturnTrue) { 4141 std::string Code = R"( 4142 bool GiveBool() { return true; } 4143 4144 void target() { 4145 bool Foo = GiveBool(); 4146 // [[p]] 4147 } 4148 )"; 4149 runDataflow(Code, 4150 [](llvm::ArrayRef< 4151 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4152 Results, 4153 ASTContext &ASTCtx) { 4154 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4155 const Environment &Env = Results[0].second.Env; 4156 4157 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4158 ASSERT_THAT(FooDecl, NotNull()); 4159 4160 auto &FooVal = 4161 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4162 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4163 }, 4164 {TransferOptions{ContextSensitiveOptions{}}}); 4165 } 4166 4167 TEST(TransferTest, ContextSensitiveReturnFalse) { 4168 std::string Code = R"( 4169 bool GiveBool() { return false; } 4170 4171 void target() { 4172 bool Foo = GiveBool(); 4173 // [[p]] 4174 } 4175 )"; 4176 runDataflow(Code, 4177 [](llvm::ArrayRef< 4178 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4179 Results, 4180 ASTContext &ASTCtx) { 4181 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4182 const Environment &Env = Results[0].second.Env; 4183 4184 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4185 ASSERT_THAT(FooDecl, NotNull()); 4186 4187 auto &FooVal = 4188 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4189 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4190 }, 4191 {TransferOptions{ContextSensitiveOptions{}}}); 4192 } 4193 4194 TEST(TransferTest, ContextSensitiveReturnArg) { 4195 std::string Code = R"( 4196 bool GiveBool(); 4197 bool GiveBack(bool Arg) { return Arg; } 4198 4199 void target() { 4200 bool Foo = GiveBool(); 4201 bool Bar = GiveBack(Foo); 4202 bool Baz = Foo == Bar; 4203 // [[p]] 4204 } 4205 )"; 4206 runDataflow(Code, 4207 [](llvm::ArrayRef< 4208 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4209 Results, 4210 ASTContext &ASTCtx) { 4211 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4212 const Environment &Env = Results[0].second.Env; 4213 4214 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4215 ASSERT_THAT(BazDecl, NotNull()); 4216 4217 auto &BazVal = 4218 *cast<BoolValue>(Env.getValue(*BazDecl, SkipPast::None)); 4219 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 4220 }, 4221 {TransferOptions{ContextSensitiveOptions{}}}); 4222 } 4223 4224 TEST(TransferTest, ContextSensitiveReturnInt) { 4225 std::string Code = R"( 4226 int identity(int x) { return x; } 4227 4228 void target() { 4229 int y = identity(42); 4230 // [[p]] 4231 } 4232 )"; 4233 runDataflow(Code, 4234 [](llvm::ArrayRef< 4235 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4236 Results, 4237 ASTContext &ASTCtx) { 4238 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4239 // This just tests that the analysis doesn't crash. 4240 }, 4241 {TransferOptions{ContextSensitiveOptions{}}}); 4242 } 4243 4244 TEST(TransferTest, ContextSensitiveMethodLiteral) { 4245 std::string Code = R"( 4246 class MyClass { 4247 public: 4248 bool giveBool() { return true; } 4249 }; 4250 4251 void target() { 4252 MyClass MyObj; 4253 bool Foo = MyObj.giveBool(); 4254 // [[p]] 4255 } 4256 )"; 4257 runDataflow(Code, 4258 [](llvm::ArrayRef< 4259 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4260 Results, 4261 ASTContext &ASTCtx) { 4262 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4263 const Environment &Env = Results[0].second.Env; 4264 4265 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4266 ASSERT_THAT(FooDecl, NotNull()); 4267 4268 auto &FooVal = 4269 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4270 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4271 }, 4272 {TransferOptions{ContextSensitiveOptions{}}}); 4273 } 4274 4275 TEST(TransferTest, ContextSensitiveMethodGetter) { 4276 std::string Code = R"( 4277 class MyClass { 4278 public: 4279 bool getField() { return Field; } 4280 4281 bool Field; 4282 }; 4283 4284 void target() { 4285 MyClass MyObj; 4286 MyObj.Field = true; 4287 bool Foo = MyObj.getField(); 4288 // [[p]] 4289 } 4290 )"; 4291 runDataflow(Code, 4292 [](llvm::ArrayRef< 4293 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4294 Results, 4295 ASTContext &ASTCtx) { 4296 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4297 const Environment &Env = Results[0].second.Env; 4298 4299 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4300 ASSERT_THAT(FooDecl, NotNull()); 4301 4302 auto &FooVal = 4303 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4304 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4305 }, 4306 {TransferOptions{ContextSensitiveOptions{}}}); 4307 } 4308 4309 TEST(TransferTest, ContextSensitiveMethodSetter) { 4310 std::string Code = R"( 4311 class MyClass { 4312 public: 4313 bool setField(bool Val) { Field = Val; } 4314 4315 bool Field; 4316 }; 4317 4318 void target() { 4319 MyClass MyObj; 4320 MyObj.setField(true); 4321 bool Foo = MyObj.Field; 4322 // [[p]] 4323 } 4324 )"; 4325 runDataflow(Code, 4326 [](llvm::ArrayRef< 4327 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4328 Results, 4329 ASTContext &ASTCtx) { 4330 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4331 const Environment &Env = Results[0].second.Env; 4332 4333 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4334 ASSERT_THAT(FooDecl, NotNull()); 4335 4336 auto &FooVal = 4337 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4338 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4339 }, 4340 {TransferOptions{ContextSensitiveOptions{}}}); 4341 } 4342 4343 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) { 4344 std::string Code = R"( 4345 class MyClass { 4346 public: 4347 bool getField() { return Field; } 4348 bool setField(bool Val) { Field = Val; } 4349 4350 private: 4351 bool Field; 4352 }; 4353 4354 void target() { 4355 MyClass MyObj; 4356 MyObj.setField(true); 4357 bool Foo = MyObj.getField(); 4358 // [[p]] 4359 } 4360 )"; 4361 runDataflow(Code, 4362 [](llvm::ArrayRef< 4363 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4364 Results, 4365 ASTContext &ASTCtx) { 4366 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4367 const Environment &Env = Results[0].second.Env; 4368 4369 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4370 ASSERT_THAT(FooDecl, NotNull()); 4371 4372 auto &FooVal = 4373 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4374 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4375 }, 4376 {TransferOptions{ContextSensitiveOptions{}}}); 4377 } 4378 4379 TEST(TransferTest, ContextSensitiveConstructorBody) { 4380 std::string Code = R"( 4381 class MyClass { 4382 public: 4383 MyClass() { MyField = true; } 4384 4385 bool MyField; 4386 }; 4387 4388 void target() { 4389 MyClass MyObj; 4390 bool Foo = MyObj.MyField; 4391 // [[p]] 4392 } 4393 )"; 4394 runDataflow(Code, 4395 [](llvm::ArrayRef< 4396 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4397 Results, 4398 ASTContext &ASTCtx) { 4399 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4400 const Environment &Env = Results[0].second.Env; 4401 4402 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4403 ASSERT_THAT(FooDecl, NotNull()); 4404 4405 auto &FooVal = 4406 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4407 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4408 }, 4409 {TransferOptions{ContextSensitiveOptions{}}}); 4410 } 4411 4412 TEST(TransferTest, ContextSensitiveConstructorInitializer) { 4413 std::string Code = R"( 4414 class MyClass { 4415 public: 4416 MyClass() : MyField(true) {} 4417 4418 bool MyField; 4419 }; 4420 4421 void target() { 4422 MyClass MyObj; 4423 bool Foo = MyObj.MyField; 4424 // [[p]] 4425 } 4426 )"; 4427 runDataflow(Code, 4428 [](llvm::ArrayRef< 4429 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4430 Results, 4431 ASTContext &ASTCtx) { 4432 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4433 const Environment &Env = Results[0].second.Env; 4434 4435 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4436 ASSERT_THAT(FooDecl, NotNull()); 4437 4438 auto &FooVal = 4439 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4440 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4441 }, 4442 {TransferOptions{ContextSensitiveOptions{}}}); 4443 } 4444 4445 TEST(TransferTest, ContextSensitiveConstructorDefault) { 4446 std::string Code = R"( 4447 class MyClass { 4448 public: 4449 MyClass() = default; 4450 4451 bool MyField = true; 4452 }; 4453 4454 void target() { 4455 MyClass MyObj; 4456 bool Foo = MyObj.MyField; 4457 // [[p]] 4458 } 4459 )"; 4460 runDataflow(Code, 4461 [](llvm::ArrayRef< 4462 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 4463 Results, 4464 ASTContext &ASTCtx) { 4465 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 4466 const Environment &Env = Results[0].second.Env; 4467 4468 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4469 ASSERT_THAT(FooDecl, NotNull()); 4470 4471 auto &FooVal = 4472 *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4473 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4474 }, 4475 {TransferOptions{ContextSensitiveOptions{}}}); 4476 } 4477 4478 } // namespace 4479