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