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 "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/StorageLocation.h" 16 #include "clang/Analysis/FlowSensitive/TestingSupport.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 39 class TransferTest : public ::testing::Test { 40 protected: 41 template <typename Matcher> 42 void runDataflow(llvm::StringRef Code, Matcher Match, 43 LangStandard::Kind Std = LangStandard::lang_cxx17, 44 bool ApplyBuiltinTransfer = true) { 45 ASSERT_THAT_ERROR( 46 test::checkDataflow<NoopAnalysis>( 47 Code, "target", 48 [ApplyBuiltinTransfer](ASTContext &C, Environment &) { 49 return NoopAnalysis(C, ApplyBuiltinTransfer); 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=" + 58 std::string( 59 LangStandard::getLangStandardForKind(Std).getName())}), 60 llvm::Succeeded()); 61 } 62 }; 63 64 TEST_F(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) { 65 std::string Code = R"( 66 void target() { 67 int Foo; 68 // [[p]] 69 } 70 )"; 71 runDataflow( 72 Code, 73 [](llvm::ArrayRef< 74 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 75 Results, 76 ASTContext &ASTCtx) { 77 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 78 const Environment &Env = Results[0].second.Env; 79 80 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 81 ASSERT_THAT(FooDecl, NotNull()); 82 83 EXPECT_EQ(Env.getStorageLocation(*FooDecl, SkipPast::None), nullptr); 84 }, 85 LangStandard::lang_cxx17, 86 /*ApplyBuiltinTransfer=*/false); 87 } 88 89 TEST_F(TransferTest, BoolVarDecl) { 90 std::string Code = R"( 91 void target() { 92 bool Foo; 93 // [[p]] 94 } 95 )"; 96 runDataflow(Code, 97 [](llvm::ArrayRef< 98 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 99 Results, 100 ASTContext &ASTCtx) { 101 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 102 const Environment &Env = Results[0].second.Env; 103 104 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 105 ASSERT_THAT(FooDecl, NotNull()); 106 107 const StorageLocation *FooLoc = 108 Env.getStorageLocation(*FooDecl, SkipPast::None); 109 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 110 111 const Value *FooVal = Env.getValue(*FooLoc); 112 EXPECT_TRUE(isa_and_nonnull<BoolValue>(FooVal)); 113 }); 114 } 115 116 TEST_F(TransferTest, IntVarDecl) { 117 std::string Code = R"( 118 void target() { 119 int Foo; 120 // [[p]] 121 } 122 )"; 123 runDataflow( 124 Code, [](llvm::ArrayRef< 125 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 126 Results, 127 ASTContext &ASTCtx) { 128 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 129 const Environment &Env = Results[0].second.Env; 130 131 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 132 ASSERT_THAT(FooDecl, NotNull()); 133 134 const StorageLocation *FooLoc = 135 Env.getStorageLocation(*FooDecl, SkipPast::None); 136 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 137 138 const Value *FooVal = Env.getValue(*FooLoc); 139 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 140 }); 141 } 142 143 TEST_F(TransferTest, StructVarDecl) { 144 std::string Code = R"( 145 struct A { 146 int Bar; 147 }; 148 149 void target() { 150 A Foo; 151 // [[p]] 152 } 153 )"; 154 runDataflow( 155 Code, [](llvm::ArrayRef< 156 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 157 Results, 158 ASTContext &ASTCtx) { 159 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 160 const Environment &Env = Results[0].second.Env; 161 162 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 163 ASSERT_THAT(FooDecl, NotNull()); 164 165 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 166 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 167 168 FieldDecl *BarDecl = nullptr; 169 for (FieldDecl *Field : FooFields) { 170 if (Field->getNameAsString() == "Bar") { 171 BarDecl = Field; 172 } else { 173 FAIL() << "Unexpected field: " << Field->getNameAsString(); 174 } 175 } 176 ASSERT_THAT(BarDecl, NotNull()); 177 178 const auto *FooLoc = cast<AggregateStorageLocation>( 179 Env.getStorageLocation(*FooDecl, SkipPast::None)); 180 const auto *BarLoc = 181 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 182 183 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 184 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 185 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 186 }); 187 } 188 189 TEST_F(TransferTest, ClassVarDecl) { 190 std::string Code = R"( 191 class A { 192 int Bar; 193 }; 194 195 void target() { 196 A Foo; 197 // [[p]] 198 } 199 )"; 200 runDataflow( 201 Code, [](llvm::ArrayRef< 202 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 203 Results, 204 ASTContext &ASTCtx) { 205 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 206 const Environment &Env = Results[0].second.Env; 207 208 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 209 ASSERT_THAT(FooDecl, NotNull()); 210 211 ASSERT_TRUE(FooDecl->getType()->isClassType()); 212 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 213 214 FieldDecl *BarDecl = nullptr; 215 for (FieldDecl *Field : FooFields) { 216 if (Field->getNameAsString() == "Bar") { 217 BarDecl = Field; 218 } else { 219 FAIL() << "Unexpected field: " << Field->getNameAsString(); 220 } 221 } 222 ASSERT_THAT(BarDecl, NotNull()); 223 224 const auto *FooLoc = cast<AggregateStorageLocation>( 225 Env.getStorageLocation(*FooDecl, SkipPast::None)); 226 const auto *BarLoc = 227 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 228 229 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 230 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 231 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 232 }); 233 } 234 235 TEST_F(TransferTest, ReferenceVarDecl) { 236 std::string Code = R"( 237 struct A {}; 238 239 A &getA(); 240 241 void target() { 242 A &Foo = getA(); 243 // [[p]] 244 } 245 )"; 246 runDataflow( 247 Code, [](llvm::ArrayRef< 248 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 249 Results, 250 ASTContext &ASTCtx) { 251 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 252 const Environment &Env = Results[0].second.Env; 253 254 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 255 ASSERT_THAT(FooDecl, NotNull()); 256 257 const StorageLocation *FooLoc = 258 Env.getStorageLocation(*FooDecl, SkipPast::None); 259 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 260 261 const ReferenceValue *FooVal = 262 cast<ReferenceValue>(Env.getValue(*FooLoc)); 263 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 264 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 265 266 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 267 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 268 }); 269 } 270 271 TEST_F(TransferTest, SelfReferentialReferenceVarDecl) { 272 std::string Code = R"( 273 struct A; 274 275 struct B {}; 276 277 struct C { 278 A &FooRef; 279 A *FooPtr; 280 B &BazRef; 281 B *BazPtr; 282 }; 283 284 struct A { 285 C &Bar; 286 }; 287 288 A &getA(); 289 290 void target() { 291 A &Foo = getA(); 292 // [[p]] 293 } 294 )"; 295 runDataflow(Code, [](llvm::ArrayRef<std::pair< 296 std::string, DataflowAnalysisState<NoopLattice>>> 297 Results, 298 ASTContext &ASTCtx) { 299 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 300 const Environment &Env = Results[0].second.Env; 301 302 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 303 ASSERT_THAT(FooDecl, NotNull()); 304 305 ASSERT_TRUE(FooDecl->getType()->isReferenceType()); 306 ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType()); 307 const auto FooFields = 308 FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields(); 309 310 FieldDecl *BarDecl = nullptr; 311 for (FieldDecl *Field : FooFields) { 312 if (Field->getNameAsString() == "Bar") { 313 BarDecl = Field; 314 } else { 315 FAIL() << "Unexpected field: " << Field->getNameAsString(); 316 } 317 } 318 ASSERT_THAT(BarDecl, NotNull()); 319 320 ASSERT_TRUE(BarDecl->getType()->isReferenceType()); 321 ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType()); 322 const auto BarFields = 323 BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields(); 324 325 FieldDecl *FooRefDecl = nullptr; 326 FieldDecl *FooPtrDecl = nullptr; 327 FieldDecl *BazRefDecl = nullptr; 328 FieldDecl *BazPtrDecl = nullptr; 329 for (FieldDecl *Field : BarFields) { 330 if (Field->getNameAsString() == "FooRef") { 331 FooRefDecl = Field; 332 } else if (Field->getNameAsString() == "FooPtr") { 333 FooPtrDecl = Field; 334 } else if (Field->getNameAsString() == "BazRef") { 335 BazRefDecl = Field; 336 } else if (Field->getNameAsString() == "BazPtr") { 337 BazPtrDecl = Field; 338 } else { 339 FAIL() << "Unexpected field: " << Field->getNameAsString(); 340 } 341 } 342 ASSERT_THAT(FooRefDecl, NotNull()); 343 ASSERT_THAT(FooPtrDecl, NotNull()); 344 ASSERT_THAT(BazRefDecl, NotNull()); 345 ASSERT_THAT(BazPtrDecl, NotNull()); 346 347 const auto *FooLoc = cast<ScalarStorageLocation>( 348 Env.getStorageLocation(*FooDecl, SkipPast::None)); 349 const auto *FooVal = cast<ReferenceValue>(Env.getValue(*FooLoc)); 350 const auto *FooPointeeVal = 351 cast<StructValue>(Env.getValue(FooVal->getPointeeLoc())); 352 353 const auto *BarVal = 354 cast<ReferenceValue>(FooPointeeVal->getChild(*BarDecl)); 355 const auto *BarPointeeVal = 356 cast<StructValue>(Env.getValue(BarVal->getPointeeLoc())); 357 358 const auto *FooRefVal = 359 cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl)); 360 const StorageLocation &FooRefPointeeLoc = FooRefVal->getPointeeLoc(); 361 EXPECT_THAT(Env.getValue(FooRefPointeeLoc), IsNull()); 362 363 const auto *FooPtrVal = 364 cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl)); 365 const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc(); 366 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull()); 367 368 const auto *BazRefVal = 369 cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl)); 370 const StorageLocation &BazRefPointeeLoc = BazRefVal->getPointeeLoc(); 371 EXPECT_THAT(Env.getValue(BazRefPointeeLoc), NotNull()); 372 373 const auto *BazPtrVal = 374 cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl)); 375 const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc(); 376 EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); 377 }); 378 } 379 380 TEST_F(TransferTest, PointerVarDecl) { 381 std::string Code = R"( 382 struct A {}; 383 384 A *getA(); 385 386 void target() { 387 A *Foo = getA(); 388 // [[p]] 389 } 390 )"; 391 runDataflow( 392 Code, [](llvm::ArrayRef< 393 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 394 Results, 395 ASTContext &ASTCtx) { 396 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 397 const Environment &Env = Results[0].second.Env; 398 399 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 400 ASSERT_THAT(FooDecl, NotNull()); 401 402 const StorageLocation *FooLoc = 403 Env.getStorageLocation(*FooDecl, SkipPast::None); 404 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 405 406 const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 407 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 408 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 409 410 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 411 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 412 }); 413 } 414 415 TEST_F(TransferTest, SelfReferentialPointerVarDecl) { 416 std::string Code = R"( 417 struct A; 418 419 struct B {}; 420 421 struct C { 422 A &FooRef; 423 A *FooPtr; 424 B &BazRef; 425 B *BazPtr; 426 }; 427 428 struct A { 429 C *Bar; 430 }; 431 432 A *getA(); 433 434 void target() { 435 A *Foo = getA(); 436 // [[p]] 437 } 438 )"; 439 runDataflow( 440 Code, [](llvm::ArrayRef< 441 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 442 Results, 443 ASTContext &ASTCtx) { 444 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 445 const Environment &Env = Results[0].second.Env; 446 447 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 448 ASSERT_THAT(FooDecl, NotNull()); 449 450 ASSERT_TRUE(FooDecl->getType()->isPointerType()); 451 ASSERT_TRUE(FooDecl->getType() 452 ->getAs<PointerType>() 453 ->getPointeeType() 454 ->isStructureType()); 455 const auto FooFields = FooDecl->getType() 456 ->getAs<PointerType>() 457 ->getPointeeType() 458 ->getAsRecordDecl() 459 ->fields(); 460 461 FieldDecl *BarDecl = nullptr; 462 for (FieldDecl *Field : FooFields) { 463 if (Field->getNameAsString() == "Bar") { 464 BarDecl = Field; 465 } else { 466 FAIL() << "Unexpected field: " << Field->getNameAsString(); 467 } 468 } 469 ASSERT_THAT(BarDecl, NotNull()); 470 471 ASSERT_TRUE(BarDecl->getType()->isPointerType()); 472 ASSERT_TRUE(BarDecl->getType() 473 ->getAs<PointerType>() 474 ->getPointeeType() 475 ->isStructureType()); 476 const auto BarFields = BarDecl->getType() 477 ->getAs<PointerType>() 478 ->getPointeeType() 479 ->getAsRecordDecl() 480 ->fields(); 481 482 FieldDecl *FooRefDecl = nullptr; 483 FieldDecl *FooPtrDecl = nullptr; 484 FieldDecl *BazRefDecl = nullptr; 485 FieldDecl *BazPtrDecl = nullptr; 486 for (FieldDecl *Field : BarFields) { 487 if (Field->getNameAsString() == "FooRef") { 488 FooRefDecl = Field; 489 } else if (Field->getNameAsString() == "FooPtr") { 490 FooPtrDecl = Field; 491 } else if (Field->getNameAsString() == "BazRef") { 492 BazRefDecl = Field; 493 } else if (Field->getNameAsString() == "BazPtr") { 494 BazPtrDecl = Field; 495 } else { 496 FAIL() << "Unexpected field: " << Field->getNameAsString(); 497 } 498 } 499 ASSERT_THAT(FooRefDecl, NotNull()); 500 ASSERT_THAT(FooPtrDecl, NotNull()); 501 ASSERT_THAT(BazRefDecl, NotNull()); 502 ASSERT_THAT(BazPtrDecl, NotNull()); 503 504 const auto *FooLoc = cast<ScalarStorageLocation>( 505 Env.getStorageLocation(*FooDecl, SkipPast::None)); 506 const auto *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 507 const auto *FooPointeeVal = 508 cast<StructValue>(Env.getValue(FooVal->getPointeeLoc())); 509 510 const auto *BarVal = 511 cast<PointerValue>(FooPointeeVal->getChild(*BarDecl)); 512 const auto *BarPointeeVal = 513 cast<StructValue>(Env.getValue(BarVal->getPointeeLoc())); 514 515 const auto *FooRefVal = 516 cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl)); 517 const StorageLocation &FooRefPointeeLoc = FooRefVal->getPointeeLoc(); 518 EXPECT_THAT(Env.getValue(FooRefPointeeLoc), IsNull()); 519 520 const auto *FooPtrVal = 521 cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl)); 522 const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc(); 523 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull()); 524 525 const auto *BazRefVal = 526 cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl)); 527 const StorageLocation &BazRefPointeeLoc = BazRefVal->getPointeeLoc(); 528 EXPECT_THAT(Env.getValue(BazRefPointeeLoc), NotNull()); 529 530 const auto *BazPtrVal = 531 cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl)); 532 const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc(); 533 EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); 534 }); 535 } 536 537 TEST_F(TransferTest, MultipleVarsDecl) { 538 std::string Code = R"( 539 void target() { 540 int Foo, Bar; 541 (void)0; 542 // [[p]] 543 } 544 )"; 545 runDataflow(Code, 546 [](llvm::ArrayRef< 547 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 548 Results, 549 ASTContext &ASTCtx) { 550 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 551 const Environment &Env = Results[0].second.Env; 552 553 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 554 ASSERT_THAT(FooDecl, NotNull()); 555 556 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 557 ASSERT_THAT(BarDecl, NotNull()); 558 559 const StorageLocation *FooLoc = 560 Env.getStorageLocation(*FooDecl, SkipPast::None); 561 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 562 563 const StorageLocation *BarLoc = 564 Env.getStorageLocation(*BarDecl, SkipPast::None); 565 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 566 567 const Value *FooVal = Env.getValue(*FooLoc); 568 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 569 570 const Value *BarVal = Env.getValue(*BarLoc); 571 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 572 }); 573 } 574 575 TEST_F(TransferTest, JoinVarDecl) { 576 std::string Code = R"( 577 void target(bool B) { 578 int Foo; 579 // [[p1]] 580 if (B) { 581 int Bar; 582 // [[p2]] 583 } else { 584 int Baz; 585 // [[p3]] 586 } 587 (void)0; 588 // [[p4]] 589 } 590 )"; 591 runDataflow(Code, [](llvm::ArrayRef<std::pair< 592 std::string, DataflowAnalysisState<NoopLattice>>> 593 Results, 594 ASTContext &ASTCtx) { 595 ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _), 596 Pair("p2", _), Pair("p1", _))); 597 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 598 ASSERT_THAT(FooDecl, NotNull()); 599 600 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 601 ASSERT_THAT(BarDecl, NotNull()); 602 603 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 604 ASSERT_THAT(BazDecl, NotNull()); 605 606 const Environment &Env1 = Results[3].second.Env; 607 const StorageLocation *FooLoc = 608 Env1.getStorageLocation(*FooDecl, SkipPast::None); 609 EXPECT_THAT(FooLoc, NotNull()); 610 EXPECT_THAT(Env1.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 611 EXPECT_THAT(Env1.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 612 613 const Environment &Env2 = Results[2].second.Env; 614 EXPECT_EQ(Env2.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 615 EXPECT_THAT(Env2.getStorageLocation(*BarDecl, SkipPast::None), NotNull()); 616 EXPECT_THAT(Env2.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 617 618 const Environment &Env3 = Results[1].second.Env; 619 EXPECT_EQ(Env3.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 620 EXPECT_THAT(Env3.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 621 EXPECT_THAT(Env3.getStorageLocation(*BazDecl, SkipPast::None), NotNull()); 622 623 const Environment &Env4 = Results[0].second.Env; 624 EXPECT_EQ(Env4.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 625 EXPECT_THAT(Env4.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 626 EXPECT_THAT(Env4.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 627 }); 628 } 629 630 TEST_F(TransferTest, BinaryOperatorAssign) { 631 std::string Code = R"( 632 void target() { 633 int Foo; 634 int Bar; 635 (Bar) = (Foo); 636 // [[p]] 637 } 638 )"; 639 runDataflow(Code, 640 [](llvm::ArrayRef< 641 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 642 Results, 643 ASTContext &ASTCtx) { 644 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 645 const Environment &Env = Results[0].second.Env; 646 647 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 648 ASSERT_THAT(FooDecl, NotNull()); 649 650 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 651 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 652 653 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 654 ASSERT_THAT(BarDecl, NotNull()); 655 656 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 657 }); 658 } 659 660 TEST_F(TransferTest, VarDeclInitAssign) { 661 std::string Code = R"( 662 void target() { 663 int Foo; 664 int Bar = Foo; 665 // [[p]] 666 } 667 )"; 668 runDataflow(Code, 669 [](llvm::ArrayRef< 670 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 671 Results, 672 ASTContext &ASTCtx) { 673 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 674 const Environment &Env = Results[0].second.Env; 675 676 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 677 ASSERT_THAT(FooDecl, NotNull()); 678 679 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 680 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 681 682 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 683 ASSERT_THAT(BarDecl, NotNull()); 684 685 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 686 }); 687 } 688 689 TEST_F(TransferTest, VarDeclInitAssignChained) { 690 std::string Code = R"( 691 void target() { 692 int Foo; 693 int Bar; 694 int Baz = (Bar = Foo); 695 // [[p]] 696 } 697 )"; 698 runDataflow(Code, 699 [](llvm::ArrayRef< 700 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 701 Results, 702 ASTContext &ASTCtx) { 703 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 704 const Environment &Env = Results[0].second.Env; 705 706 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 707 ASSERT_THAT(FooDecl, NotNull()); 708 709 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 710 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 711 712 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 713 ASSERT_THAT(BarDecl, NotNull()); 714 715 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 716 ASSERT_THAT(BazDecl, NotNull()); 717 718 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 719 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal); 720 }); 721 } 722 723 TEST_F(TransferTest, VarDeclInitAssignPtrDeref) { 724 std::string Code = R"( 725 void target() { 726 int Foo; 727 int *Bar; 728 *(Bar) = Foo; 729 int Baz = *(Bar); 730 // [[p]] 731 } 732 )"; 733 runDataflow(Code, 734 [](llvm::ArrayRef< 735 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 736 Results, 737 ASTContext &ASTCtx) { 738 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 739 const Environment &Env = Results[0].second.Env; 740 741 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 742 ASSERT_THAT(FooDecl, NotNull()); 743 744 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 745 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 746 747 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 748 ASSERT_THAT(BarDecl, NotNull()); 749 750 const auto *BarVal = 751 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 752 EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal); 753 754 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 755 ASSERT_THAT(BazDecl, NotNull()); 756 757 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal); 758 }); 759 } 760 761 TEST_F(TransferTest, AssignToAndFromReference) { 762 std::string Code = R"( 763 void target() { 764 int Foo; 765 int Bar; 766 int &Baz = Foo; 767 // [[p1]] 768 Baz = Bar; 769 int Qux = Baz; 770 int &Quux = Baz; 771 // [[p2]] 772 } 773 )"; 774 runDataflow( 775 Code, [](llvm::ArrayRef< 776 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 777 Results, 778 ASTContext &ASTCtx) { 779 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 780 const Environment &Env1 = Results[0].second.Env; 781 const Environment &Env2 = Results[1].second.Env; 782 783 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 784 ASSERT_THAT(FooDecl, NotNull()); 785 786 const Value *FooVal = Env1.getValue(*FooDecl, SkipPast::None); 787 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 788 789 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 790 ASSERT_THAT(BarDecl, NotNull()); 791 792 const Value *BarVal = Env1.getValue(*BarDecl, SkipPast::None); 793 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 794 795 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 796 ASSERT_THAT(BazDecl, NotNull()); 797 798 EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), FooVal); 799 800 EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BarVal); 801 EXPECT_EQ(Env2.getValue(*FooDecl, SkipPast::None), BarVal); 802 803 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 804 ASSERT_THAT(QuxDecl, NotNull()); 805 EXPECT_EQ(Env2.getValue(*QuxDecl, SkipPast::None), BarVal); 806 807 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 808 ASSERT_THAT(QuuxDecl, NotNull()); 809 EXPECT_EQ(Env2.getValue(*QuuxDecl, SkipPast::Reference), BarVal); 810 }); 811 } 812 813 TEST_F(TransferTest, MultipleParamDecls) { 814 std::string Code = R"( 815 void target(int Foo, int Bar) { 816 (void)0; 817 // [[p]] 818 } 819 )"; 820 runDataflow(Code, 821 [](llvm::ArrayRef< 822 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 823 Results, 824 ASTContext &ASTCtx) { 825 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 826 const Environment &Env = Results[0].second.Env; 827 828 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 829 ASSERT_THAT(FooDecl, NotNull()); 830 831 const StorageLocation *FooLoc = 832 Env.getStorageLocation(*FooDecl, SkipPast::None); 833 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 834 835 const Value *FooVal = Env.getValue(*FooLoc); 836 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 837 838 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 839 ASSERT_THAT(BarDecl, NotNull()); 840 841 const StorageLocation *BarLoc = 842 Env.getStorageLocation(*BarDecl, SkipPast::None); 843 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 844 845 const Value *BarVal = Env.getValue(*BarLoc); 846 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 847 }); 848 } 849 850 TEST_F(TransferTest, StructParamDecl) { 851 std::string Code = R"( 852 struct A { 853 int Bar; 854 }; 855 856 void target(A Foo) { 857 (void)0; 858 // [[p]] 859 } 860 )"; 861 runDataflow( 862 Code, [](llvm::ArrayRef< 863 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 864 Results, 865 ASTContext &ASTCtx) { 866 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 867 const Environment &Env = Results[0].second.Env; 868 869 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 870 ASSERT_THAT(FooDecl, NotNull()); 871 872 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 873 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 874 875 FieldDecl *BarDecl = nullptr; 876 for (FieldDecl *Field : FooFields) { 877 if (Field->getNameAsString() == "Bar") { 878 BarDecl = Field; 879 } else { 880 FAIL() << "Unexpected field: " << Field->getNameAsString(); 881 } 882 } 883 ASSERT_THAT(BarDecl, NotNull()); 884 885 const auto *FooLoc = cast<AggregateStorageLocation>( 886 Env.getStorageLocation(*FooDecl, SkipPast::None)); 887 const auto *BarLoc = 888 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 889 890 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 891 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 892 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 893 }); 894 } 895 896 TEST_F(TransferTest, ReferenceParamDecl) { 897 std::string Code = R"( 898 struct A {}; 899 900 void target(A &Foo) { 901 (void)0; 902 // [[p]] 903 } 904 )"; 905 runDataflow(Code, 906 [](llvm::ArrayRef< 907 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 908 Results, 909 ASTContext &ASTCtx) { 910 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 911 const Environment &Env = Results[0].second.Env; 912 913 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 914 ASSERT_THAT(FooDecl, NotNull()); 915 916 const StorageLocation *FooLoc = 917 Env.getStorageLocation(*FooDecl, SkipPast::None); 918 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 919 920 const ReferenceValue *FooVal = 921 dyn_cast<ReferenceValue>(Env.getValue(*FooLoc)); 922 ASSERT_THAT(FooVal, NotNull()); 923 924 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 925 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 926 927 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 928 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 929 }); 930 } 931 932 TEST_F(TransferTest, PointerParamDecl) { 933 std::string Code = R"( 934 struct A {}; 935 936 void target(A *Foo) { 937 (void)0; 938 // [[p]] 939 } 940 )"; 941 runDataflow( 942 Code, [](llvm::ArrayRef< 943 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 944 Results, 945 ASTContext &ASTCtx) { 946 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 947 const Environment &Env = Results[0].second.Env; 948 949 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 950 ASSERT_THAT(FooDecl, NotNull()); 951 952 const StorageLocation *FooLoc = 953 Env.getStorageLocation(*FooDecl, SkipPast::None); 954 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 955 956 const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 957 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 958 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 959 960 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 961 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 962 }); 963 } 964 965 TEST_F(TransferTest, StructMember) { 966 std::string Code = R"( 967 struct A { 968 int Bar; 969 }; 970 971 void target(A Foo) { 972 int Baz = Foo.Bar; 973 // [[p]] 974 } 975 )"; 976 runDataflow( 977 Code, [](llvm::ArrayRef< 978 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 979 Results, 980 ASTContext &ASTCtx) { 981 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 982 const Environment &Env = Results[0].second.Env; 983 984 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 985 ASSERT_THAT(FooDecl, NotNull()); 986 987 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 988 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 989 990 FieldDecl *BarDecl = nullptr; 991 for (FieldDecl *Field : FooFields) { 992 if (Field->getNameAsString() == "Bar") { 993 BarDecl = Field; 994 } else { 995 FAIL() << "Unexpected field: " << Field->getNameAsString(); 996 } 997 } 998 ASSERT_THAT(BarDecl, NotNull()); 999 1000 const auto *FooLoc = cast<AggregateStorageLocation>( 1001 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1002 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1003 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1004 1005 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1006 ASSERT_THAT(BazDecl, NotNull()); 1007 1008 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal); 1009 }); 1010 } 1011 1012 TEST_F(TransferTest, ClassMember) { 1013 std::string Code = R"( 1014 class A { 1015 public: 1016 int Bar; 1017 }; 1018 1019 void target(A Foo) { 1020 int Baz = Foo.Bar; 1021 // [[p]] 1022 } 1023 )"; 1024 runDataflow( 1025 Code, [](llvm::ArrayRef< 1026 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1027 Results, 1028 ASTContext &ASTCtx) { 1029 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1030 const Environment &Env = Results[0].second.Env; 1031 1032 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1033 ASSERT_THAT(FooDecl, NotNull()); 1034 1035 ASSERT_TRUE(FooDecl->getType()->isClassType()); 1036 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1037 1038 FieldDecl *BarDecl = nullptr; 1039 for (FieldDecl *Field : FooFields) { 1040 if (Field->getNameAsString() == "Bar") { 1041 BarDecl = Field; 1042 } else { 1043 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1044 } 1045 } 1046 ASSERT_THAT(BarDecl, NotNull()); 1047 1048 const auto *FooLoc = cast<AggregateStorageLocation>( 1049 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1050 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1051 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1052 1053 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1054 ASSERT_THAT(BazDecl, NotNull()); 1055 1056 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal); 1057 }); 1058 } 1059 1060 TEST_F(TransferTest, ReferenceMember) { 1061 std::string Code = R"( 1062 struct A { 1063 int &Bar; 1064 }; 1065 1066 void target(A Foo) { 1067 int Baz = Foo.Bar; 1068 // [[p]] 1069 } 1070 )"; 1071 runDataflow( 1072 Code, [](llvm::ArrayRef< 1073 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1074 Results, 1075 ASTContext &ASTCtx) { 1076 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1077 const Environment &Env = Results[0].second.Env; 1078 1079 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1080 ASSERT_THAT(FooDecl, NotNull()); 1081 1082 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1083 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1084 1085 FieldDecl *BarDecl = nullptr; 1086 for (FieldDecl *Field : FooFields) { 1087 if (Field->getNameAsString() == "Bar") { 1088 BarDecl = Field; 1089 } else { 1090 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1091 } 1092 } 1093 ASSERT_THAT(BarDecl, NotNull()); 1094 1095 const auto *FooLoc = cast<AggregateStorageLocation>( 1096 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1097 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1098 const auto *BarVal = cast<ReferenceValue>(FooVal->getChild(*BarDecl)); 1099 const auto *BarPointeeVal = 1100 cast<IntegerValue>(Env.getValue(BarVal->getPointeeLoc())); 1101 1102 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1103 ASSERT_THAT(BazDecl, NotNull()); 1104 1105 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarPointeeVal); 1106 }); 1107 } 1108 1109 TEST_F(TransferTest, StructThisMember) { 1110 std::string Code = R"( 1111 struct A { 1112 int Bar; 1113 1114 struct B { 1115 int Baz; 1116 }; 1117 1118 B Qux; 1119 1120 void target() { 1121 int Foo = Bar; 1122 int Quux = Qux.Baz; 1123 // [[p]] 1124 } 1125 }; 1126 )"; 1127 runDataflow( 1128 Code, [](llvm::ArrayRef< 1129 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1130 Results, 1131 ASTContext &ASTCtx) { 1132 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1133 const Environment &Env = Results[0].second.Env; 1134 1135 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1136 Env.getThisPointeeStorageLocation()); 1137 ASSERT_THAT(ThisLoc, NotNull()); 1138 1139 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1140 ASSERT_THAT(BarDecl, NotNull()); 1141 1142 const auto *BarLoc = 1143 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1144 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1145 1146 const Value *BarVal = Env.getValue(*BarLoc); 1147 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1148 1149 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1150 ASSERT_THAT(FooDecl, NotNull()); 1151 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1152 1153 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1154 ASSERT_THAT(QuxDecl, NotNull()); 1155 1156 ASSERT_TRUE(QuxDecl->getType()->isStructureType()); 1157 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1158 1159 FieldDecl *BazDecl = nullptr; 1160 for (FieldDecl *Field : QuxFields) { 1161 if (Field->getNameAsString() == "Baz") { 1162 BazDecl = Field; 1163 } else { 1164 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1165 } 1166 } 1167 ASSERT_THAT(BazDecl, NotNull()); 1168 1169 const auto *QuxLoc = 1170 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1171 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1172 ASSERT_THAT(QuxVal, NotNull()); 1173 1174 const auto *BazLoc = 1175 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1176 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1177 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1178 1179 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1180 ASSERT_THAT(QuuxDecl, NotNull()); 1181 EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal); 1182 }); 1183 } 1184 1185 TEST_F(TransferTest, ClassThisMember) { 1186 std::string Code = R"( 1187 class A { 1188 int Bar; 1189 1190 class B { 1191 public: 1192 int Baz; 1193 }; 1194 1195 B Qux; 1196 1197 void target() { 1198 int Foo = Bar; 1199 int Quux = Qux.Baz; 1200 // [[p]] 1201 } 1202 }; 1203 )"; 1204 runDataflow( 1205 Code, [](llvm::ArrayRef< 1206 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1207 Results, 1208 ASTContext &ASTCtx) { 1209 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1210 const Environment &Env = Results[0].second.Env; 1211 1212 const auto *ThisLoc = 1213 cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation()); 1214 1215 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1216 ASSERT_THAT(BarDecl, NotNull()); 1217 1218 const auto *BarLoc = 1219 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1220 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1221 1222 const Value *BarVal = Env.getValue(*BarLoc); 1223 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1224 1225 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1226 ASSERT_THAT(FooDecl, NotNull()); 1227 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1228 1229 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1230 ASSERT_THAT(QuxDecl, NotNull()); 1231 1232 ASSERT_TRUE(QuxDecl->getType()->isClassType()); 1233 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1234 1235 FieldDecl *BazDecl = nullptr; 1236 for (FieldDecl *Field : QuxFields) { 1237 if (Field->getNameAsString() == "Baz") { 1238 BazDecl = Field; 1239 } else { 1240 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1241 } 1242 } 1243 ASSERT_THAT(BazDecl, NotNull()); 1244 1245 const auto *QuxLoc = 1246 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1247 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1248 ASSERT_THAT(QuxVal, NotNull()); 1249 1250 const auto *BazLoc = 1251 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1252 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1253 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1254 1255 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1256 ASSERT_THAT(QuuxDecl, NotNull()); 1257 EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal); 1258 }); 1259 } 1260 1261 TEST_F(TransferTest, ConstructorInitializer) { 1262 std::string Code = R"( 1263 struct target { 1264 int Bar; 1265 1266 target(int Foo) : Bar(Foo) { 1267 int Qux = Bar; 1268 // [[p]] 1269 } 1270 }; 1271 )"; 1272 runDataflow(Code, 1273 [](llvm::ArrayRef< 1274 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1275 Results, 1276 ASTContext &ASTCtx) { 1277 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1278 const Environment &Env = Results[0].second.Env; 1279 1280 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1281 Env.getThisPointeeStorageLocation()); 1282 ASSERT_THAT(ThisLoc, NotNull()); 1283 1284 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1285 ASSERT_THAT(FooDecl, NotNull()); 1286 1287 const auto *FooVal = 1288 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1289 1290 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1291 ASSERT_THAT(QuxDecl, NotNull()); 1292 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1293 }); 1294 } 1295 1296 TEST_F(TransferTest, DefaultInitializer) { 1297 std::string Code = R"( 1298 struct target { 1299 int Bar; 1300 int Baz = Bar; 1301 1302 target(int Foo) : Bar(Foo) { 1303 int Qux = Baz; 1304 // [[p]] 1305 } 1306 }; 1307 )"; 1308 runDataflow(Code, 1309 [](llvm::ArrayRef< 1310 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1311 Results, 1312 ASTContext &ASTCtx) { 1313 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1314 const Environment &Env = Results[0].second.Env; 1315 1316 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1317 Env.getThisPointeeStorageLocation()); 1318 ASSERT_THAT(ThisLoc, NotNull()); 1319 1320 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1321 ASSERT_THAT(FooDecl, NotNull()); 1322 1323 const auto *FooVal = 1324 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1325 1326 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1327 ASSERT_THAT(QuxDecl, NotNull()); 1328 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1329 }); 1330 } 1331 1332 TEST_F(TransferTest, DefaultInitializerReference) { 1333 std::string Code = R"( 1334 struct target { 1335 int &Bar; 1336 int &Baz = Bar; 1337 1338 target(int &Foo) : Bar(Foo) { 1339 int &Qux = Baz; 1340 // [[p]] 1341 } 1342 }; 1343 )"; 1344 runDataflow( 1345 Code, [](llvm::ArrayRef< 1346 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1347 Results, 1348 ASTContext &ASTCtx) { 1349 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1350 const Environment &Env = Results[0].second.Env; 1351 1352 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1353 Env.getThisPointeeStorageLocation()); 1354 ASSERT_THAT(ThisLoc, NotNull()); 1355 1356 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1357 ASSERT_THAT(FooDecl, NotNull()); 1358 1359 const auto *FooVal = 1360 cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None)); 1361 1362 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1363 ASSERT_THAT(QuxDecl, NotNull()); 1364 1365 const auto *QuxVal = 1366 cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None)); 1367 EXPECT_EQ(&QuxVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 1368 }); 1369 } 1370 1371 TEST_F(TransferTest, TemporaryObject) { 1372 std::string Code = R"( 1373 struct A { 1374 int Bar; 1375 }; 1376 1377 void target() { 1378 A Foo = A(); 1379 // [[p]] 1380 } 1381 )"; 1382 runDataflow( 1383 Code, [](llvm::ArrayRef< 1384 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1385 Results, 1386 ASTContext &ASTCtx) { 1387 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1388 const Environment &Env = Results[0].second.Env; 1389 1390 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1391 ASSERT_THAT(FooDecl, NotNull()); 1392 1393 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1394 ASSERT_THAT(BarDecl, NotNull()); 1395 1396 const auto *FooLoc = cast<AggregateStorageLocation>( 1397 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1398 const auto *BarLoc = 1399 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1400 1401 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1402 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1403 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1404 }); 1405 } 1406 1407 TEST_F(TransferTest, ElidableConstructor) { 1408 // This test is effectively the same as TransferTest.TemporaryObject, but 1409 // the code is compiled as C++ 14. 1410 std::string Code = R"( 1411 struct A { 1412 int Bar; 1413 }; 1414 1415 void target() { 1416 A Foo = A(); 1417 // [[p]] 1418 } 1419 )"; 1420 runDataflow( 1421 Code, 1422 [](llvm::ArrayRef< 1423 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1424 Results, 1425 ASTContext &ASTCtx) { 1426 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1427 const Environment &Env = Results[0].second.Env; 1428 1429 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1430 ASSERT_THAT(FooDecl, NotNull()); 1431 1432 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1433 ASSERT_THAT(BarDecl, NotNull()); 1434 1435 const auto *FooLoc = cast<AggregateStorageLocation>( 1436 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1437 const auto *BarLoc = 1438 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1439 1440 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1441 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1442 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1443 }, 1444 LangStandard::lang_cxx14); 1445 } 1446 1447 TEST_F(TransferTest, AssignmentOperator) { 1448 std::string Code = R"( 1449 struct A { 1450 int Baz; 1451 }; 1452 1453 void target() { 1454 A Foo; 1455 A Bar; 1456 // [[p1]] 1457 Foo = Bar; 1458 // [[p2]] 1459 } 1460 )"; 1461 runDataflow( 1462 Code, [](llvm::ArrayRef< 1463 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1464 Results, 1465 ASTContext &ASTCtx) { 1466 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 1467 const Environment &Env1 = Results[0].second.Env; 1468 const Environment &Env2 = Results[1].second.Env; 1469 1470 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1471 ASSERT_THAT(FooDecl, NotNull()); 1472 1473 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1474 ASSERT_THAT(BarDecl, NotNull()); 1475 1476 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1477 ASSERT_THAT(BazDecl, NotNull()); 1478 1479 const auto *FooLoc1 = cast<AggregateStorageLocation>( 1480 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 1481 const auto *BarLoc1 = cast<AggregateStorageLocation>( 1482 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 1483 1484 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 1485 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 1486 EXPECT_NE(FooVal1, BarVal1); 1487 1488 const auto *FooBazVal1 = 1489 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 1490 const auto *BarBazVal1 = 1491 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 1492 EXPECT_NE(FooBazVal1, BarBazVal1); 1493 1494 const auto *FooLoc2 = cast<AggregateStorageLocation>( 1495 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 1496 const auto *BarLoc2 = cast<AggregateStorageLocation>( 1497 Env2.getStorageLocation(*BarDecl, SkipPast::None)); 1498 1499 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 1500 const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2)); 1501 EXPECT_EQ(FooVal2, BarVal2); 1502 1503 const auto *FooBazVal2 = 1504 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 1505 const auto *BarBazVal2 = 1506 cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl))); 1507 EXPECT_EQ(FooBazVal2, BarBazVal2); 1508 }); 1509 } 1510 1511 TEST_F(TransferTest, CopyConstructor) { 1512 std::string Code = R"( 1513 struct A { 1514 int Baz; 1515 }; 1516 1517 void target() { 1518 A Foo; 1519 A Bar = Foo; 1520 // [[p]] 1521 } 1522 )"; 1523 runDataflow( 1524 Code, [](llvm::ArrayRef< 1525 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1526 Results, 1527 ASTContext &ASTCtx) { 1528 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1529 const Environment &Env = Results[0].second.Env; 1530 1531 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1532 ASSERT_THAT(FooDecl, NotNull()); 1533 1534 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1535 ASSERT_THAT(BarDecl, NotNull()); 1536 1537 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1538 ASSERT_THAT(BazDecl, NotNull()); 1539 1540 const auto *FooLoc = cast<AggregateStorageLocation>( 1541 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1542 const auto *BarLoc = cast<AggregateStorageLocation>( 1543 Env.getStorageLocation(*BarDecl, SkipPast::None)); 1544 1545 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1546 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 1547 EXPECT_EQ(FooVal, BarVal); 1548 1549 const auto *FooBazVal = 1550 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 1551 const auto *BarBazVal = 1552 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 1553 EXPECT_EQ(FooBazVal, BarBazVal); 1554 }); 1555 } 1556 1557 TEST_F(TransferTest, CopyConstructorWithParens) { 1558 std::string Code = R"( 1559 struct A { 1560 int Baz; 1561 }; 1562 1563 void target() { 1564 A Foo; 1565 A Bar((A(Foo))); 1566 // [[p]] 1567 } 1568 )"; 1569 runDataflow( 1570 Code, [](llvm::ArrayRef< 1571 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1572 Results, 1573 ASTContext &ASTCtx) { 1574 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1575 const Environment &Env = Results[0].second.Env; 1576 1577 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1578 ASSERT_THAT(FooDecl, NotNull()); 1579 1580 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1581 ASSERT_THAT(BarDecl, NotNull()); 1582 1583 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1584 ASSERT_THAT(BazDecl, NotNull()); 1585 1586 const auto *FooLoc = cast<AggregateStorageLocation>( 1587 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1588 const auto *BarLoc = cast<AggregateStorageLocation>( 1589 Env.getStorageLocation(*BarDecl, SkipPast::None)); 1590 1591 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1592 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 1593 EXPECT_EQ(FooVal, BarVal); 1594 1595 const auto *FooBazVal = 1596 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 1597 const auto *BarBazVal = 1598 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 1599 EXPECT_EQ(FooBazVal, BarBazVal); 1600 }); 1601 } 1602 1603 TEST_F(TransferTest, MoveConstructor) { 1604 std::string Code = R"( 1605 namespace std { 1606 1607 template <typename T> struct remove_reference { using type = T; }; 1608 template <typename T> struct remove_reference<T&> { using type = T; }; 1609 template <typename T> struct remove_reference<T&&> { using type = T; }; 1610 1611 template <typename T> 1612 using remove_reference_t = typename remove_reference<T>::type; 1613 1614 template <typename T> 1615 std::remove_reference_t<T>&& move(T&& x); 1616 1617 } // namespace std 1618 1619 struct A { 1620 int Baz; 1621 }; 1622 1623 void target() { 1624 A Foo; 1625 A Bar; 1626 // [[p1]] 1627 Foo = std::move(Bar); 1628 // [[p2]] 1629 } 1630 )"; 1631 runDataflow( 1632 Code, [](llvm::ArrayRef< 1633 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1634 Results, 1635 ASTContext &ASTCtx) { 1636 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 1637 const Environment &Env1 = Results[0].second.Env; 1638 const Environment &Env2 = Results[1].second.Env; 1639 1640 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1641 ASSERT_THAT(FooDecl, NotNull()); 1642 1643 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1644 ASSERT_THAT(BarDecl, NotNull()); 1645 1646 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1647 ASSERT_THAT(BazDecl, NotNull()); 1648 1649 const auto *FooLoc1 = cast<AggregateStorageLocation>( 1650 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 1651 const auto *BarLoc1 = cast<AggregateStorageLocation>( 1652 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 1653 1654 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 1655 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 1656 EXPECT_NE(FooVal1, BarVal1); 1657 1658 const auto *FooBazVal1 = 1659 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 1660 const auto *BarBazVal1 = 1661 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 1662 EXPECT_NE(FooBazVal1, BarBazVal1); 1663 1664 const auto *FooLoc2 = cast<AggregateStorageLocation>( 1665 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 1666 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 1667 EXPECT_EQ(FooVal2, BarVal1); 1668 1669 const auto *FooBazVal2 = 1670 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 1671 EXPECT_EQ(FooBazVal2, BarBazVal1); 1672 }); 1673 } 1674 1675 TEST_F(TransferTest, BindTemporary) { 1676 std::string Code = R"( 1677 struct A { 1678 virtual ~A() = default; 1679 1680 int Baz; 1681 }; 1682 1683 void target(A Foo) { 1684 int Bar = A(Foo).Baz; 1685 // [[p]] 1686 } 1687 )"; 1688 runDataflow(Code, 1689 [](llvm::ArrayRef< 1690 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1691 Results, 1692 ASTContext &ASTCtx) { 1693 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1694 const Environment &Env = Results[0].second.Env; 1695 1696 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1697 ASSERT_THAT(FooDecl, NotNull()); 1698 1699 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1700 ASSERT_THAT(BarDecl, NotNull()); 1701 1702 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1703 ASSERT_THAT(BazDecl, NotNull()); 1704 1705 const auto &FooVal = 1706 *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 1707 const auto *BarVal = 1708 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 1709 EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl)); 1710 }); 1711 } 1712 1713 TEST_F(TransferTest, StaticCast) { 1714 std::string Code = R"( 1715 void target(int Foo) { 1716 int Bar = static_cast<int>(Foo); 1717 // [[p]] 1718 } 1719 )"; 1720 runDataflow(Code, 1721 [](llvm::ArrayRef< 1722 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1723 Results, 1724 ASTContext &ASTCtx) { 1725 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1726 const Environment &Env = Results[0].second.Env; 1727 1728 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1729 ASSERT_THAT(FooDecl, NotNull()); 1730 1731 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1732 ASSERT_THAT(BarDecl, NotNull()); 1733 1734 const auto *FooVal = 1735 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1736 const auto *BarVal = 1737 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 1738 EXPECT_EQ(FooVal, BarVal); 1739 }); 1740 } 1741 1742 TEST_F(TransferTest, AddrOfValue) { 1743 std::string Code = R"( 1744 void target() { 1745 int Foo; 1746 int *Bar = &Foo; 1747 // [[p]] 1748 } 1749 )"; 1750 runDataflow(Code, 1751 [](llvm::ArrayRef< 1752 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1753 Results, 1754 ASTContext &ASTCtx) { 1755 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1756 const Environment &Env = Results[0].second.Env; 1757 1758 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1759 ASSERT_THAT(FooDecl, NotNull()); 1760 1761 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1762 ASSERT_THAT(BarDecl, NotNull()); 1763 1764 const auto *FooLoc = cast<ScalarStorageLocation>( 1765 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1766 const auto *BarVal = 1767 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 1768 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc); 1769 }); 1770 } 1771 1772 TEST_F(TransferTest, AddrOfReference) { 1773 std::string Code = R"( 1774 void target(int *Foo) { 1775 int *Bar = &(*Foo); 1776 // [[p]] 1777 } 1778 )"; 1779 runDataflow(Code, 1780 [](llvm::ArrayRef< 1781 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1782 Results, 1783 ASTContext &ASTCtx) { 1784 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1785 const Environment &Env = Results[0].second.Env; 1786 1787 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1788 ASSERT_THAT(FooDecl, NotNull()); 1789 1790 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1791 ASSERT_THAT(BarDecl, NotNull()); 1792 1793 const auto *FooVal = 1794 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1795 const auto *BarVal = 1796 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 1797 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 1798 }); 1799 } 1800 1801 TEST_F(TransferTest, DerefDependentPtr) { 1802 std::string Code = R"( 1803 template <typename T> 1804 void target(T *Foo) { 1805 T &Bar = *Foo; 1806 /*[[p]]*/ 1807 } 1808 )"; 1809 runDataflow( 1810 Code, [](llvm::ArrayRef< 1811 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1812 Results, 1813 ASTContext &ASTCtx) { 1814 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1815 const Environment &Env = Results[0].second.Env; 1816 1817 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1818 ASSERT_THAT(FooDecl, NotNull()); 1819 1820 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1821 ASSERT_THAT(BarDecl, NotNull()); 1822 1823 const auto *FooVal = 1824 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1825 const auto *BarVal = 1826 cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None)); 1827 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 1828 }); 1829 } 1830 1831 TEST_F(TransferTest, VarDeclInitAssignConditionalOperator) { 1832 std::string Code = R"( 1833 struct A {}; 1834 1835 void target(A Foo, A Bar, bool Cond) { 1836 A Baz = Cond ? Foo : Bar; 1837 /*[[p]]*/ 1838 } 1839 )"; 1840 runDataflow( 1841 Code, [](llvm::ArrayRef< 1842 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1843 Results, 1844 ASTContext &ASTCtx) { 1845 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1846 const Environment &Env = Results[0].second.Env; 1847 1848 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1849 ASSERT_THAT(FooDecl, NotNull()); 1850 1851 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1852 ASSERT_THAT(BarDecl, NotNull()); 1853 1854 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1855 ASSERT_THAT(BazDecl, NotNull()); 1856 1857 const auto *FooVal = 1858 cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 1859 const auto *BarVal = 1860 cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None)); 1861 1862 const auto *BazVal = 1863 dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None)); 1864 ASSERT_THAT(BazVal, NotNull()); 1865 1866 EXPECT_NE(BazVal, FooVal); 1867 EXPECT_NE(BazVal, BarVal); 1868 }); 1869 } 1870 1871 TEST_F(TransferTest, VarDeclInDoWhile) { 1872 std::string Code = R"( 1873 void target(int *Foo) { 1874 do { 1875 int Bar = *Foo; 1876 } while (true); 1877 (void)0; 1878 /*[[p]]*/ 1879 } 1880 )"; 1881 runDataflow(Code, 1882 [](llvm::ArrayRef< 1883 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1884 Results, 1885 ASTContext &ASTCtx) { 1886 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1887 const Environment &Env = Results[0].second.Env; 1888 1889 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1890 ASSERT_THAT(FooDecl, NotNull()); 1891 1892 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1893 ASSERT_THAT(BarDecl, NotNull()); 1894 1895 const auto *FooVal = 1896 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1897 const auto *FooPointeeVal = 1898 cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc())); 1899 1900 const auto *BarVal = dyn_cast_or_null<IntegerValue>( 1901 Env.getValue(*BarDecl, SkipPast::None)); 1902 ASSERT_THAT(BarVal, NotNull()); 1903 1904 EXPECT_EQ(BarVal, FooPointeeVal); 1905 }); 1906 } 1907 1908 TEST_F(TransferTest, AggregateInitialization) { 1909 std::string BracesCode = R"( 1910 struct A { 1911 int Foo; 1912 }; 1913 1914 struct B { 1915 int Bar; 1916 A Baz; 1917 int Qux; 1918 }; 1919 1920 void target(int BarArg, int FooArg, int QuxArg) { 1921 B Quux{BarArg, {FooArg}, QuxArg}; 1922 /*[[p]]*/ 1923 } 1924 )"; 1925 std::string BraceEllisionCode = R"( 1926 struct A { 1927 int Foo; 1928 }; 1929 1930 struct B { 1931 int Bar; 1932 A Baz; 1933 int Qux; 1934 }; 1935 1936 void target(int BarArg, int FooArg, int QuxArg) { 1937 B Quux = {BarArg, FooArg, QuxArg}; 1938 /*[[p]]*/ 1939 } 1940 )"; 1941 for (const std::string &Code : {BracesCode, BraceEllisionCode}) { 1942 runDataflow( 1943 Code, [](llvm::ArrayRef< 1944 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1945 Results, 1946 ASTContext &ASTCtx) { 1947 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1948 const Environment &Env = Results[0].second.Env; 1949 1950 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1951 ASSERT_THAT(FooDecl, NotNull()); 1952 1953 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1954 ASSERT_THAT(BarDecl, NotNull()); 1955 1956 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1957 ASSERT_THAT(BazDecl, NotNull()); 1958 1959 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1960 ASSERT_THAT(QuxDecl, NotNull()); 1961 1962 const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg"); 1963 ASSERT_THAT(FooArgDecl, NotNull()); 1964 1965 const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg"); 1966 ASSERT_THAT(BarArgDecl, NotNull()); 1967 1968 const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg"); 1969 ASSERT_THAT(QuxArgDecl, NotNull()); 1970 1971 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1972 ASSERT_THAT(QuuxDecl, NotNull()); 1973 1974 const auto *FooArgVal = 1975 cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None)); 1976 const auto *BarArgVal = 1977 cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None)); 1978 const auto *QuxArgVal = 1979 cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None)); 1980 1981 const auto *QuuxVal = 1982 cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None)); 1983 ASSERT_THAT(QuuxVal, NotNull()); 1984 1985 const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl)); 1986 ASSERT_THAT(BazVal, NotNull()); 1987 1988 EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal); 1989 EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal); 1990 EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal); 1991 }); 1992 } 1993 } 1994 1995 TEST_F(TransferTest, AssignToUnionMember) { 1996 std::string Code = R"( 1997 union A { 1998 int Foo; 1999 }; 2000 2001 void target(int Bar) { 2002 A Baz; 2003 Baz.Foo = Bar; 2004 // [[p]] 2005 } 2006 )"; 2007 runDataflow(Code, 2008 [](llvm::ArrayRef< 2009 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2010 Results, 2011 ASTContext &ASTCtx) { 2012 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2013 const Environment &Env = Results[0].second.Env; 2014 2015 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2016 ASSERT_THAT(BazDecl, NotNull()); 2017 ASSERT_TRUE(BazDecl->getType()->isUnionType()); 2018 2019 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>( 2020 Env.getStorageLocation(*BazDecl, SkipPast::None)); 2021 ASSERT_THAT(BazLoc, NotNull()); 2022 2023 // FIXME: Add support for union types. 2024 EXPECT_THAT(Env.getValue(*BazLoc), IsNull()); 2025 }); 2026 } 2027 2028 TEST_F(TransferTest, AssignFromBoolLiteral) { 2029 std::string Code = R"( 2030 void target() { 2031 bool Foo = true; 2032 bool Bar = false; 2033 // [[p]] 2034 } 2035 )"; 2036 runDataflow(Code, 2037 [](llvm::ArrayRef< 2038 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2039 Results, 2040 ASTContext &ASTCtx) { 2041 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2042 const Environment &Env = Results[0].second.Env; 2043 2044 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2045 ASSERT_THAT(FooDecl, NotNull()); 2046 2047 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2048 Env.getValue(*FooDecl, SkipPast::None)); 2049 ASSERT_THAT(FooVal, NotNull()); 2050 2051 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2052 ASSERT_THAT(BarDecl, NotNull()); 2053 2054 const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>( 2055 Env.getValue(*BarDecl, SkipPast::None)); 2056 ASSERT_THAT(BarVal, NotNull()); 2057 2058 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true)); 2059 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false)); 2060 }); 2061 } 2062 2063 TEST_F(TransferTest, AssignFromBoolConjunction) { 2064 std::string Code = R"( 2065 void target(bool Foo, bool Bar) { 2066 bool Baz = (Foo) && (Bar); 2067 // [[p]] 2068 } 2069 )"; 2070 runDataflow( 2071 Code, [](llvm::ArrayRef< 2072 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2073 Results, 2074 ASTContext &ASTCtx) { 2075 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2076 const Environment &Env = Results[0].second.Env; 2077 2078 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2079 ASSERT_THAT(FooDecl, NotNull()); 2080 2081 const auto *FooVal = 2082 dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 2083 ASSERT_THAT(FooVal, NotNull()); 2084 2085 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2086 ASSERT_THAT(BarDecl, NotNull()); 2087 2088 const auto *BarVal = 2089 dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 2090 ASSERT_THAT(BarVal, NotNull()); 2091 2092 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2093 ASSERT_THAT(BazDecl, NotNull()); 2094 2095 const auto *BazVal = dyn_cast_or_null<ConjunctionValue>( 2096 Env.getValue(*BazDecl, SkipPast::None)); 2097 ASSERT_THAT(BazVal, NotNull()); 2098 2099 EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal); 2100 EXPECT_EQ(&BazVal->getRightSubValue(), BarVal); 2101 }); 2102 } 2103 2104 TEST_F(TransferTest, AssignFromBoolDisjunction) { 2105 std::string Code = R"( 2106 void target(bool Foo, bool Bar) { 2107 bool Baz = (Foo) || (Bar); 2108 // [[p]] 2109 } 2110 )"; 2111 runDataflow( 2112 Code, [](llvm::ArrayRef< 2113 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2114 Results, 2115 ASTContext &ASTCtx) { 2116 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2117 const Environment &Env = Results[0].second.Env; 2118 2119 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2120 ASSERT_THAT(FooDecl, NotNull()); 2121 2122 const auto *FooVal = 2123 dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 2124 ASSERT_THAT(FooVal, NotNull()); 2125 2126 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2127 ASSERT_THAT(BarDecl, NotNull()); 2128 2129 const auto *BarVal = 2130 dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 2131 ASSERT_THAT(BarVal, NotNull()); 2132 2133 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2134 ASSERT_THAT(BazDecl, NotNull()); 2135 2136 const auto *BazVal = dyn_cast_or_null<DisjunctionValue>( 2137 Env.getValue(*BazDecl, SkipPast::None)); 2138 ASSERT_THAT(BazVal, NotNull()); 2139 2140 EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal); 2141 EXPECT_EQ(&BazVal->getRightSubValue(), BarVal); 2142 }); 2143 } 2144 2145 TEST_F(TransferTest, AssignFromBoolNegation) { 2146 std::string Code = R"( 2147 void target() { 2148 bool Foo = true; 2149 bool Bar = !(Foo); 2150 // [[p]] 2151 } 2152 )"; 2153 runDataflow(Code, 2154 [](llvm::ArrayRef< 2155 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2156 Results, 2157 ASTContext &ASTCtx) { 2158 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2159 const Environment &Env = Results[0].second.Env; 2160 2161 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2162 ASSERT_THAT(FooDecl, NotNull()); 2163 2164 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2165 Env.getValue(*FooDecl, SkipPast::None)); 2166 ASSERT_THAT(FooVal, NotNull()); 2167 2168 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2169 ASSERT_THAT(BarDecl, NotNull()); 2170 2171 const auto *BarVal = dyn_cast_or_null<NegationValue>( 2172 Env.getValue(*BarDecl, SkipPast::None)); 2173 ASSERT_THAT(BarVal, NotNull()); 2174 2175 EXPECT_EQ(&BarVal->getSubVal(), FooVal); 2176 }); 2177 } 2178 2179 TEST_F(TransferTest, StaticIntSingleVarDecl) { 2180 std::string Code = R"( 2181 void target() { 2182 static int Foo; 2183 // [[p]] 2184 } 2185 )"; 2186 runDataflow(Code, 2187 [](llvm::ArrayRef< 2188 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2189 Results, 2190 ASTContext &ASTCtx) { 2191 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2192 const Environment &Env = Results[0].second.Env; 2193 2194 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2195 ASSERT_THAT(FooDecl, NotNull()); 2196 2197 const StorageLocation *FooLoc = 2198 Env.getStorageLocation(*FooDecl, SkipPast::None); 2199 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 2200 2201 const Value *FooVal = Env.getValue(*FooLoc); 2202 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 2203 }); 2204 } 2205 2206 TEST_F(TransferTest, StaticIntGroupVarDecl) { 2207 std::string Code = R"( 2208 void target() { 2209 static int Foo, Bar; 2210 (void)0; 2211 // [[p]] 2212 } 2213 )"; 2214 runDataflow(Code, 2215 [](llvm::ArrayRef< 2216 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2217 Results, 2218 ASTContext &ASTCtx) { 2219 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2220 const Environment &Env = Results[0].second.Env; 2221 2222 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2223 ASSERT_THAT(FooDecl, NotNull()); 2224 2225 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2226 ASSERT_THAT(BarDecl, NotNull()); 2227 2228 const StorageLocation *FooLoc = 2229 Env.getStorageLocation(*FooDecl, SkipPast::None); 2230 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 2231 2232 const StorageLocation *BarLoc = 2233 Env.getStorageLocation(*BarDecl, SkipPast::None); 2234 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 2235 2236 const Value *FooVal = Env.getValue(*FooLoc); 2237 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 2238 2239 const Value *BarVal = Env.getValue(*BarLoc); 2240 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 2241 2242 EXPECT_NE(FooVal, BarVal); 2243 }); 2244 } 2245 2246 TEST_F(TransferTest, GlobalIntVarDecl) { 2247 std::string Code = R"( 2248 static int Foo; 2249 2250 void target() { 2251 int Bar = Foo; 2252 int Baz = Foo; 2253 // [[p]] 2254 } 2255 )"; 2256 runDataflow(Code, 2257 [](llvm::ArrayRef< 2258 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2259 Results, 2260 ASTContext &ASTCtx) { 2261 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2262 const Environment &Env = Results[0].second.Env; 2263 2264 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2265 ASSERT_THAT(BarDecl, NotNull()); 2266 2267 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2268 ASSERT_THAT(BazDecl, NotNull()); 2269 2270 const Value *BarVal = 2271 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2272 const Value *BazVal = 2273 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2274 EXPECT_EQ(BarVal, BazVal); 2275 }); 2276 } 2277 2278 TEST_F(TransferTest, StaticMemberIntVarDecl) { 2279 std::string Code = R"( 2280 struct A { 2281 static int Foo; 2282 }; 2283 2284 void target(A a) { 2285 int Bar = a.Foo; 2286 int Baz = a.Foo; 2287 // [[p]] 2288 } 2289 )"; 2290 runDataflow(Code, 2291 [](llvm::ArrayRef< 2292 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2293 Results, 2294 ASTContext &ASTCtx) { 2295 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2296 const Environment &Env = Results[0].second.Env; 2297 2298 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2299 ASSERT_THAT(BarDecl, NotNull()); 2300 2301 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2302 ASSERT_THAT(BazDecl, NotNull()); 2303 2304 const Value *BarVal = 2305 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2306 const Value *BazVal = 2307 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2308 EXPECT_EQ(BarVal, BazVal); 2309 }); 2310 } 2311 2312 TEST_F(TransferTest, StaticMemberRefVarDecl) { 2313 std::string Code = R"( 2314 struct A { 2315 static int &Foo; 2316 }; 2317 2318 void target(A a) { 2319 int Bar = a.Foo; 2320 int Baz = a.Foo; 2321 // [[p]] 2322 } 2323 )"; 2324 runDataflow(Code, 2325 [](llvm::ArrayRef< 2326 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2327 Results, 2328 ASTContext &ASTCtx) { 2329 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2330 const Environment &Env = Results[0].second.Env; 2331 2332 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2333 ASSERT_THAT(BarDecl, NotNull()); 2334 2335 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2336 ASSERT_THAT(BazDecl, NotNull()); 2337 2338 const Value *BarVal = 2339 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2340 const Value *BazVal = 2341 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2342 EXPECT_EQ(BarVal, BazVal); 2343 }); 2344 } 2345 2346 TEST_F(TransferTest, AssignMemberBeforeCopy) { 2347 std::string Code = R"( 2348 struct A { 2349 int Foo; 2350 }; 2351 2352 void target() { 2353 A A1; 2354 A A2; 2355 int Bar; 2356 A1.Foo = Bar; 2357 A2 = A1; 2358 // [[p]] 2359 } 2360 )"; 2361 runDataflow(Code, 2362 [](llvm::ArrayRef< 2363 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2364 Results, 2365 ASTContext &ASTCtx) { 2366 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2367 const Environment &Env = Results[0].second.Env; 2368 2369 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2370 ASSERT_THAT(FooDecl, NotNull()); 2371 2372 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2373 ASSERT_THAT(BarDecl, NotNull()); 2374 2375 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); 2376 ASSERT_THAT(A1Decl, NotNull()); 2377 2378 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); 2379 ASSERT_THAT(A2Decl, NotNull()); 2380 2381 const auto *BarVal = 2382 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2383 2384 const auto *A2Val = 2385 cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None)); 2386 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal); 2387 }); 2388 } 2389 2390 } // namespace 2391