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