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 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, DerivedBaseMemberClass) { 1013 std::string Code = R"( 1014 class A { 1015 int ADefault; 1016 protected: 1017 int AProtected; 1018 private: 1019 int APrivate; 1020 public: 1021 int APublic; 1022 }; 1023 1024 class B : public A { 1025 int BDefault; 1026 protected: 1027 int BProtected; 1028 private: 1029 int BPrivate; 1030 }; 1031 1032 void target() { 1033 B Foo; 1034 // [[p]] 1035 } 1036 )"; 1037 runDataflow( 1038 Code, [](llvm::ArrayRef< 1039 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1040 Results, 1041 ASTContext &ASTCtx) { 1042 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1043 const Environment &Env = Results[0].second.Env; 1044 1045 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1046 ASSERT_THAT(FooDecl, NotNull()); 1047 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1048 1049 // Derived-class fields. 1050 const FieldDecl *BDefaultDecl = nullptr; 1051 const FieldDecl *BProtectedDecl = nullptr; 1052 const FieldDecl *BPrivateDecl = nullptr; 1053 for (const FieldDecl *Field : 1054 FooDecl->getType()->getAsRecordDecl()->fields()) { 1055 if (Field->getNameAsString() == "BDefault") { 1056 BDefaultDecl = Field; 1057 } else if (Field->getNameAsString() == "BProtected") { 1058 BProtectedDecl = Field; 1059 } else if (Field->getNameAsString() == "BPrivate") { 1060 BPrivateDecl = Field; 1061 } else { 1062 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1063 } 1064 } 1065 ASSERT_THAT(BDefaultDecl, NotNull()); 1066 ASSERT_THAT(BProtectedDecl, NotNull()); 1067 ASSERT_THAT(BPrivateDecl, NotNull()); 1068 1069 // Base-class fields. 1070 const FieldDecl *ADefaultDecl = nullptr; 1071 const FieldDecl *APrivateDecl = nullptr; 1072 const FieldDecl *AProtectedDecl = nullptr; 1073 const FieldDecl *APublicDecl = nullptr; 1074 for (const clang::CXXBaseSpecifier &Base : 1075 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1076 QualType BaseType = Base.getType(); 1077 ASSERT_TRUE(BaseType->isRecordType()); 1078 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1079 if (Field->getNameAsString() == "ADefault") { 1080 ADefaultDecl = Field; 1081 } else if (Field->getNameAsString() == "AProtected") { 1082 AProtectedDecl = Field; 1083 } else if (Field->getNameAsString() == "APrivate") { 1084 APrivateDecl = Field; 1085 } else if (Field->getNameAsString() == "APublic") { 1086 APublicDecl = Field; 1087 } else { 1088 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1089 } 1090 } 1091 } 1092 ASSERT_THAT(ADefaultDecl, NotNull()); 1093 ASSERT_THAT(AProtectedDecl, NotNull()); 1094 ASSERT_THAT(APrivateDecl, NotNull()); 1095 ASSERT_THAT(APublicDecl, NotNull()); 1096 1097 const auto &FooLoc = *cast<AggregateStorageLocation>( 1098 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1099 const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc)); 1100 1101 // Note: we can't test presence of children in `FooLoc`, because 1102 // `getChild` requires its argument be present (or fails an assert). So, 1103 // we limit to testing presence in `FooVal` and coherence between the 1104 // two. 1105 1106 // Base-class fields. 1107 EXPECT_THAT(FooVal.getChild(*ADefaultDecl), IsNull()); 1108 EXPECT_THAT(FooVal.getChild(*APrivateDecl), IsNull()); 1109 1110 EXPECT_THAT(FooVal.getChild(*AProtectedDecl), NotNull()); 1111 EXPECT_EQ(Env.getValue(FooLoc.getChild(*APublicDecl)), 1112 FooVal.getChild(*APublicDecl)); 1113 EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull()); 1114 EXPECT_EQ(Env.getValue(FooLoc.getChild(*AProtectedDecl)), 1115 FooVal.getChild(*AProtectedDecl)); 1116 1117 // Derived-class fields. 1118 EXPECT_THAT(FooVal.getChild(*BDefaultDecl), NotNull()); 1119 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BDefaultDecl)), 1120 FooVal.getChild(*BDefaultDecl)); 1121 EXPECT_THAT(FooVal.getChild(*BProtectedDecl), NotNull()); 1122 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BProtectedDecl)), 1123 FooVal.getChild(*BProtectedDecl)); 1124 EXPECT_THAT(FooVal.getChild(*BPrivateDecl), NotNull()); 1125 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BPrivateDecl)), 1126 FooVal.getChild(*BPrivateDecl)); 1127 }); 1128 } 1129 1130 TEST_F(TransferTest, DerivedBaseMemberStructDefault) { 1131 std::string Code = R"( 1132 struct A { 1133 int Bar; 1134 }; 1135 struct B : public A { 1136 }; 1137 1138 void target() { 1139 B Foo; 1140 // [[p]] 1141 } 1142 )"; 1143 runDataflow( 1144 Code, [](llvm::ArrayRef< 1145 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1146 Results, 1147 ASTContext &ASTCtx) { 1148 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1149 const Environment &Env = Results[0].second.Env; 1150 1151 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1152 ASSERT_THAT(FooDecl, NotNull()); 1153 1154 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1155 const FieldDecl *BarDecl = nullptr; 1156 for (const clang::CXXBaseSpecifier &Base : 1157 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1158 QualType BaseType = Base.getType(); 1159 ASSERT_TRUE(BaseType->isStructureType()); 1160 1161 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1162 if (Field->getNameAsString() == "Bar") { 1163 BarDecl = Field; 1164 } else { 1165 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1166 } 1167 } 1168 } 1169 ASSERT_THAT(BarDecl, NotNull()); 1170 1171 const auto &FooLoc = *cast<AggregateStorageLocation>( 1172 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1173 const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc)); 1174 EXPECT_THAT(FooVal.getChild(*BarDecl), NotNull()); 1175 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BarDecl)), 1176 FooVal.getChild(*BarDecl)); 1177 }); 1178 } 1179 1180 TEST_F(TransferTest, ClassMember) { 1181 std::string Code = R"( 1182 class A { 1183 public: 1184 int Bar; 1185 }; 1186 1187 void target(A Foo) { 1188 int Baz = Foo.Bar; 1189 // [[p]] 1190 } 1191 )"; 1192 runDataflow( 1193 Code, [](llvm::ArrayRef< 1194 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1195 Results, 1196 ASTContext &ASTCtx) { 1197 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1198 const Environment &Env = Results[0].second.Env; 1199 1200 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1201 ASSERT_THAT(FooDecl, NotNull()); 1202 1203 ASSERT_TRUE(FooDecl->getType()->isClassType()); 1204 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1205 1206 FieldDecl *BarDecl = nullptr; 1207 for (FieldDecl *Field : FooFields) { 1208 if (Field->getNameAsString() == "Bar") { 1209 BarDecl = Field; 1210 } else { 1211 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1212 } 1213 } 1214 ASSERT_THAT(BarDecl, NotNull()); 1215 1216 const auto *FooLoc = cast<AggregateStorageLocation>( 1217 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1218 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1219 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1220 1221 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1222 ASSERT_THAT(BazDecl, NotNull()); 1223 1224 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal); 1225 }); 1226 } 1227 1228 TEST_F(TransferTest, ReferenceMember) { 1229 std::string Code = R"( 1230 struct A { 1231 int &Bar; 1232 }; 1233 1234 void target(A Foo) { 1235 int Baz = Foo.Bar; 1236 // [[p]] 1237 } 1238 )"; 1239 runDataflow( 1240 Code, [](llvm::ArrayRef< 1241 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1242 Results, 1243 ASTContext &ASTCtx) { 1244 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1245 const Environment &Env = Results[0].second.Env; 1246 1247 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1248 ASSERT_THAT(FooDecl, NotNull()); 1249 1250 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1251 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1252 1253 FieldDecl *BarDecl = nullptr; 1254 for (FieldDecl *Field : FooFields) { 1255 if (Field->getNameAsString() == "Bar") { 1256 BarDecl = Field; 1257 } else { 1258 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1259 } 1260 } 1261 ASSERT_THAT(BarDecl, NotNull()); 1262 1263 const auto *FooLoc = cast<AggregateStorageLocation>( 1264 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1265 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1266 const auto *BarVal = cast<ReferenceValue>(FooVal->getChild(*BarDecl)); 1267 const auto *BarPointeeVal = 1268 cast<IntegerValue>(Env.getValue(BarVal->getPointeeLoc())); 1269 1270 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1271 ASSERT_THAT(BazDecl, NotNull()); 1272 1273 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarPointeeVal); 1274 }); 1275 } 1276 1277 TEST_F(TransferTest, StructThisMember) { 1278 std::string Code = R"( 1279 struct A { 1280 int Bar; 1281 1282 struct B { 1283 int Baz; 1284 }; 1285 1286 B Qux; 1287 1288 void target() { 1289 int Foo = Bar; 1290 int Quux = Qux.Baz; 1291 // [[p]] 1292 } 1293 }; 1294 )"; 1295 runDataflow( 1296 Code, [](llvm::ArrayRef< 1297 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1298 Results, 1299 ASTContext &ASTCtx) { 1300 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1301 const Environment &Env = Results[0].second.Env; 1302 1303 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1304 Env.getThisPointeeStorageLocation()); 1305 ASSERT_THAT(ThisLoc, NotNull()); 1306 1307 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1308 ASSERT_THAT(BarDecl, NotNull()); 1309 1310 const auto *BarLoc = 1311 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1312 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1313 1314 const Value *BarVal = Env.getValue(*BarLoc); 1315 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1316 1317 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1318 ASSERT_THAT(FooDecl, NotNull()); 1319 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1320 1321 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1322 ASSERT_THAT(QuxDecl, NotNull()); 1323 1324 ASSERT_TRUE(QuxDecl->getType()->isStructureType()); 1325 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1326 1327 FieldDecl *BazDecl = nullptr; 1328 for (FieldDecl *Field : QuxFields) { 1329 if (Field->getNameAsString() == "Baz") { 1330 BazDecl = Field; 1331 } else { 1332 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1333 } 1334 } 1335 ASSERT_THAT(BazDecl, NotNull()); 1336 1337 const auto *QuxLoc = 1338 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1339 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1340 ASSERT_THAT(QuxVal, NotNull()); 1341 1342 const auto *BazLoc = 1343 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1344 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1345 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1346 1347 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1348 ASSERT_THAT(QuuxDecl, NotNull()); 1349 EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal); 1350 }); 1351 } 1352 1353 TEST_F(TransferTest, ClassThisMember) { 1354 std::string Code = R"( 1355 class A { 1356 int Bar; 1357 1358 class B { 1359 public: 1360 int Baz; 1361 }; 1362 1363 B Qux; 1364 1365 void target() { 1366 int Foo = Bar; 1367 int Quux = Qux.Baz; 1368 // [[p]] 1369 } 1370 }; 1371 )"; 1372 runDataflow( 1373 Code, [](llvm::ArrayRef< 1374 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1375 Results, 1376 ASTContext &ASTCtx) { 1377 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1378 const Environment &Env = Results[0].second.Env; 1379 1380 const auto *ThisLoc = 1381 cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation()); 1382 1383 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1384 ASSERT_THAT(BarDecl, NotNull()); 1385 1386 const auto *BarLoc = 1387 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1388 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1389 1390 const Value *BarVal = Env.getValue(*BarLoc); 1391 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1392 1393 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1394 ASSERT_THAT(FooDecl, NotNull()); 1395 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1396 1397 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1398 ASSERT_THAT(QuxDecl, NotNull()); 1399 1400 ASSERT_TRUE(QuxDecl->getType()->isClassType()); 1401 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1402 1403 FieldDecl *BazDecl = nullptr; 1404 for (FieldDecl *Field : QuxFields) { 1405 if (Field->getNameAsString() == "Baz") { 1406 BazDecl = Field; 1407 } else { 1408 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1409 } 1410 } 1411 ASSERT_THAT(BazDecl, NotNull()); 1412 1413 const auto *QuxLoc = 1414 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1415 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1416 ASSERT_THAT(QuxVal, NotNull()); 1417 1418 const auto *BazLoc = 1419 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1420 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1421 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1422 1423 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1424 ASSERT_THAT(QuuxDecl, NotNull()); 1425 EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal); 1426 }); 1427 } 1428 1429 TEST_F(TransferTest, ConstructorInitializer) { 1430 std::string Code = R"( 1431 struct target { 1432 int Bar; 1433 1434 target(int Foo) : Bar(Foo) { 1435 int Qux = Bar; 1436 // [[p]] 1437 } 1438 }; 1439 )"; 1440 runDataflow(Code, 1441 [](llvm::ArrayRef< 1442 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1443 Results, 1444 ASTContext &ASTCtx) { 1445 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1446 const Environment &Env = Results[0].second.Env; 1447 1448 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1449 Env.getThisPointeeStorageLocation()); 1450 ASSERT_THAT(ThisLoc, NotNull()); 1451 1452 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1453 ASSERT_THAT(FooDecl, NotNull()); 1454 1455 const auto *FooVal = 1456 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1457 1458 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1459 ASSERT_THAT(QuxDecl, NotNull()); 1460 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1461 }); 1462 } 1463 1464 TEST_F(TransferTest, DefaultInitializer) { 1465 std::string Code = R"( 1466 struct target { 1467 int Bar; 1468 int Baz = Bar; 1469 1470 target(int Foo) : Bar(Foo) { 1471 int Qux = Baz; 1472 // [[p]] 1473 } 1474 }; 1475 )"; 1476 runDataflow(Code, 1477 [](llvm::ArrayRef< 1478 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1479 Results, 1480 ASTContext &ASTCtx) { 1481 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1482 const Environment &Env = Results[0].second.Env; 1483 1484 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1485 Env.getThisPointeeStorageLocation()); 1486 ASSERT_THAT(ThisLoc, NotNull()); 1487 1488 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1489 ASSERT_THAT(FooDecl, NotNull()); 1490 1491 const auto *FooVal = 1492 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1493 1494 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1495 ASSERT_THAT(QuxDecl, NotNull()); 1496 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1497 }); 1498 } 1499 1500 TEST_F(TransferTest, DefaultInitializerReference) { 1501 std::string Code = R"( 1502 struct target { 1503 int &Bar; 1504 int &Baz = Bar; 1505 1506 target(int &Foo) : Bar(Foo) { 1507 int &Qux = Baz; 1508 // [[p]] 1509 } 1510 }; 1511 )"; 1512 runDataflow( 1513 Code, [](llvm::ArrayRef< 1514 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1515 Results, 1516 ASTContext &ASTCtx) { 1517 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1518 const Environment &Env = Results[0].second.Env; 1519 1520 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1521 Env.getThisPointeeStorageLocation()); 1522 ASSERT_THAT(ThisLoc, NotNull()); 1523 1524 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1525 ASSERT_THAT(FooDecl, NotNull()); 1526 1527 const auto *FooVal = 1528 cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None)); 1529 1530 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1531 ASSERT_THAT(QuxDecl, NotNull()); 1532 1533 const auto *QuxVal = 1534 cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None)); 1535 EXPECT_EQ(&QuxVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 1536 }); 1537 } 1538 1539 TEST_F(TransferTest, TemporaryObject) { 1540 std::string Code = R"( 1541 struct A { 1542 int Bar; 1543 }; 1544 1545 void target() { 1546 A Foo = A(); 1547 // [[p]] 1548 } 1549 )"; 1550 runDataflow( 1551 Code, [](llvm::ArrayRef< 1552 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1553 Results, 1554 ASTContext &ASTCtx) { 1555 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1556 const Environment &Env = Results[0].second.Env; 1557 1558 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1559 ASSERT_THAT(FooDecl, NotNull()); 1560 1561 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1562 ASSERT_THAT(BarDecl, NotNull()); 1563 1564 const auto *FooLoc = cast<AggregateStorageLocation>( 1565 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1566 const auto *BarLoc = 1567 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1568 1569 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1570 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1571 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1572 }); 1573 } 1574 1575 TEST_F(TransferTest, ElidableConstructor) { 1576 // This test is effectively the same as TransferTest.TemporaryObject, but 1577 // the code is compiled as C++ 14. 1578 std::string Code = R"( 1579 struct A { 1580 int Bar; 1581 }; 1582 1583 void target() { 1584 A Foo = A(); 1585 // [[p]] 1586 } 1587 )"; 1588 runDataflow( 1589 Code, 1590 [](llvm::ArrayRef< 1591 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1592 Results, 1593 ASTContext &ASTCtx) { 1594 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1595 const Environment &Env = Results[0].second.Env; 1596 1597 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1598 ASSERT_THAT(FooDecl, NotNull()); 1599 1600 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1601 ASSERT_THAT(BarDecl, NotNull()); 1602 1603 const auto *FooLoc = cast<AggregateStorageLocation>( 1604 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1605 const auto *BarLoc = 1606 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1607 1608 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1609 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1610 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1611 }, 1612 LangStandard::lang_cxx14); 1613 } 1614 1615 TEST_F(TransferTest, AssignmentOperator) { 1616 std::string Code = R"( 1617 struct A { 1618 int Baz; 1619 }; 1620 1621 void target() { 1622 A Foo; 1623 A Bar; 1624 // [[p1]] 1625 Foo = Bar; 1626 // [[p2]] 1627 } 1628 )"; 1629 runDataflow( 1630 Code, [](llvm::ArrayRef< 1631 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1632 Results, 1633 ASTContext &ASTCtx) { 1634 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 1635 const Environment &Env1 = Results[0].second.Env; 1636 const Environment &Env2 = Results[1].second.Env; 1637 1638 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1639 ASSERT_THAT(FooDecl, NotNull()); 1640 1641 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1642 ASSERT_THAT(BarDecl, NotNull()); 1643 1644 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1645 ASSERT_THAT(BazDecl, NotNull()); 1646 1647 const auto *FooLoc1 = cast<AggregateStorageLocation>( 1648 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 1649 const auto *BarLoc1 = cast<AggregateStorageLocation>( 1650 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 1651 1652 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 1653 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 1654 EXPECT_NE(FooVal1, BarVal1); 1655 1656 const auto *FooBazVal1 = 1657 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 1658 const auto *BarBazVal1 = 1659 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 1660 EXPECT_NE(FooBazVal1, BarBazVal1); 1661 1662 const auto *FooLoc2 = cast<AggregateStorageLocation>( 1663 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 1664 const auto *BarLoc2 = cast<AggregateStorageLocation>( 1665 Env2.getStorageLocation(*BarDecl, SkipPast::None)); 1666 1667 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 1668 const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2)); 1669 EXPECT_EQ(FooVal2, BarVal2); 1670 1671 const auto *FooBazVal2 = 1672 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 1673 const auto *BarBazVal2 = 1674 cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl))); 1675 EXPECT_EQ(FooBazVal2, BarBazVal2); 1676 }); 1677 } 1678 1679 TEST_F(TransferTest, CopyConstructor) { 1680 std::string Code = R"( 1681 struct A { 1682 int Baz; 1683 }; 1684 1685 void target() { 1686 A Foo; 1687 A Bar = Foo; 1688 // [[p]] 1689 } 1690 )"; 1691 runDataflow( 1692 Code, [](llvm::ArrayRef< 1693 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1694 Results, 1695 ASTContext &ASTCtx) { 1696 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1697 const Environment &Env = Results[0].second.Env; 1698 1699 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1700 ASSERT_THAT(FooDecl, NotNull()); 1701 1702 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1703 ASSERT_THAT(BarDecl, NotNull()); 1704 1705 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1706 ASSERT_THAT(BazDecl, NotNull()); 1707 1708 const auto *FooLoc = cast<AggregateStorageLocation>( 1709 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1710 const auto *BarLoc = cast<AggregateStorageLocation>( 1711 Env.getStorageLocation(*BarDecl, SkipPast::None)); 1712 1713 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1714 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 1715 EXPECT_EQ(FooVal, BarVal); 1716 1717 const auto *FooBazVal = 1718 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 1719 const auto *BarBazVal = 1720 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 1721 EXPECT_EQ(FooBazVal, BarBazVal); 1722 }); 1723 } 1724 1725 TEST_F(TransferTest, CopyConstructorWithParens) { 1726 std::string Code = R"( 1727 struct A { 1728 int Baz; 1729 }; 1730 1731 void target() { 1732 A Foo; 1733 A Bar((A(Foo))); 1734 // [[p]] 1735 } 1736 )"; 1737 runDataflow( 1738 Code, [](llvm::ArrayRef< 1739 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1740 Results, 1741 ASTContext &ASTCtx) { 1742 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1743 const Environment &Env = Results[0].second.Env; 1744 1745 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1746 ASSERT_THAT(FooDecl, NotNull()); 1747 1748 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1749 ASSERT_THAT(BarDecl, NotNull()); 1750 1751 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1752 ASSERT_THAT(BazDecl, NotNull()); 1753 1754 const auto *FooLoc = cast<AggregateStorageLocation>( 1755 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1756 const auto *BarLoc = cast<AggregateStorageLocation>( 1757 Env.getStorageLocation(*BarDecl, SkipPast::None)); 1758 1759 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1760 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 1761 EXPECT_EQ(FooVal, BarVal); 1762 1763 const auto *FooBazVal = 1764 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 1765 const auto *BarBazVal = 1766 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 1767 EXPECT_EQ(FooBazVal, BarBazVal); 1768 }); 1769 } 1770 1771 TEST_F(TransferTest, MoveConstructor) { 1772 std::string Code = R"( 1773 namespace std { 1774 1775 template <typename T> struct remove_reference { using type = T; }; 1776 template <typename T> struct remove_reference<T&> { using type = T; }; 1777 template <typename T> struct remove_reference<T&&> { using type = T; }; 1778 1779 template <typename T> 1780 using remove_reference_t = typename remove_reference<T>::type; 1781 1782 template <typename T> 1783 std::remove_reference_t<T>&& move(T&& x); 1784 1785 } // namespace std 1786 1787 struct A { 1788 int Baz; 1789 }; 1790 1791 void target() { 1792 A Foo; 1793 A Bar; 1794 // [[p1]] 1795 Foo = std::move(Bar); 1796 // [[p2]] 1797 } 1798 )"; 1799 runDataflow( 1800 Code, [](llvm::ArrayRef< 1801 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1802 Results, 1803 ASTContext &ASTCtx) { 1804 ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _))); 1805 const Environment &Env1 = Results[0].second.Env; 1806 const Environment &Env2 = Results[1].second.Env; 1807 1808 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1809 ASSERT_THAT(FooDecl, NotNull()); 1810 1811 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1812 ASSERT_THAT(BarDecl, NotNull()); 1813 1814 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1815 ASSERT_THAT(BazDecl, NotNull()); 1816 1817 const auto *FooLoc1 = cast<AggregateStorageLocation>( 1818 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 1819 const auto *BarLoc1 = cast<AggregateStorageLocation>( 1820 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 1821 1822 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 1823 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 1824 EXPECT_NE(FooVal1, BarVal1); 1825 1826 const auto *FooBazVal1 = 1827 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 1828 const auto *BarBazVal1 = 1829 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 1830 EXPECT_NE(FooBazVal1, BarBazVal1); 1831 1832 const auto *FooLoc2 = cast<AggregateStorageLocation>( 1833 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 1834 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 1835 EXPECT_EQ(FooVal2, BarVal1); 1836 1837 const auto *FooBazVal2 = 1838 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 1839 EXPECT_EQ(FooBazVal2, BarBazVal1); 1840 }); 1841 } 1842 1843 TEST_F(TransferTest, BindTemporary) { 1844 std::string Code = R"( 1845 struct A { 1846 virtual ~A() = default; 1847 1848 int Baz; 1849 }; 1850 1851 void target(A Foo) { 1852 int Bar = A(Foo).Baz; 1853 // [[p]] 1854 } 1855 )"; 1856 runDataflow(Code, 1857 [](llvm::ArrayRef< 1858 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1859 Results, 1860 ASTContext &ASTCtx) { 1861 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1862 const Environment &Env = Results[0].second.Env; 1863 1864 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1865 ASSERT_THAT(FooDecl, NotNull()); 1866 1867 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1868 ASSERT_THAT(BarDecl, NotNull()); 1869 1870 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1871 ASSERT_THAT(BazDecl, NotNull()); 1872 1873 const auto &FooVal = 1874 *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 1875 const auto *BarVal = 1876 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 1877 EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl)); 1878 }); 1879 } 1880 1881 TEST_F(TransferTest, StaticCast) { 1882 std::string Code = R"( 1883 void target(int Foo) { 1884 int Bar = static_cast<int>(Foo); 1885 // [[p]] 1886 } 1887 )"; 1888 runDataflow(Code, 1889 [](llvm::ArrayRef< 1890 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1891 Results, 1892 ASTContext &ASTCtx) { 1893 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1894 const Environment &Env = Results[0].second.Env; 1895 1896 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1897 ASSERT_THAT(FooDecl, NotNull()); 1898 1899 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1900 ASSERT_THAT(BarDecl, NotNull()); 1901 1902 const auto *FooVal = 1903 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1904 const auto *BarVal = 1905 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 1906 EXPECT_EQ(FooVal, BarVal); 1907 }); 1908 } 1909 1910 TEST_F(TransferTest, AddrOfValue) { 1911 std::string Code = R"( 1912 void target() { 1913 int Foo; 1914 int *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 *FooLoc = cast<ScalarStorageLocation>( 1933 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1934 const auto *BarVal = 1935 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 1936 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc); 1937 }); 1938 } 1939 1940 TEST_F(TransferTest, AddrOfReference) { 1941 std::string Code = R"( 1942 void target(int *Foo) { 1943 int *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 = 1962 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1963 const auto *BarVal = 1964 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 1965 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 1966 }); 1967 } 1968 1969 TEST_F(TransferTest, DerefDependentPtr) { 1970 std::string Code = R"( 1971 template <typename T> 1972 void target(T *Foo) { 1973 T &Bar = *Foo; 1974 /*[[p]]*/ 1975 } 1976 )"; 1977 runDataflow( 1978 Code, [](llvm::ArrayRef< 1979 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 1980 Results, 1981 ASTContext &ASTCtx) { 1982 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 1983 const Environment &Env = Results[0].second.Env; 1984 1985 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1986 ASSERT_THAT(FooDecl, NotNull()); 1987 1988 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1989 ASSERT_THAT(BarDecl, NotNull()); 1990 1991 const auto *FooVal = 1992 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1993 const auto *BarVal = 1994 cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None)); 1995 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 1996 }); 1997 } 1998 1999 TEST_F(TransferTest, VarDeclInitAssignConditionalOperator) { 2000 std::string Code = R"( 2001 struct A {}; 2002 2003 void target(A Foo, A Bar, bool Cond) { 2004 A Baz = Cond ? Foo : Bar; 2005 /*[[p]]*/ 2006 } 2007 )"; 2008 runDataflow( 2009 Code, [](llvm::ArrayRef< 2010 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2011 Results, 2012 ASTContext &ASTCtx) { 2013 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2014 const Environment &Env = Results[0].second.Env; 2015 2016 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2017 ASSERT_THAT(FooDecl, NotNull()); 2018 2019 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2020 ASSERT_THAT(BarDecl, NotNull()); 2021 2022 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2023 ASSERT_THAT(BazDecl, NotNull()); 2024 2025 const auto *FooVal = 2026 cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 2027 const auto *BarVal = 2028 cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None)); 2029 2030 const auto *BazVal = 2031 dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None)); 2032 ASSERT_THAT(BazVal, NotNull()); 2033 2034 EXPECT_NE(BazVal, FooVal); 2035 EXPECT_NE(BazVal, BarVal); 2036 }); 2037 } 2038 2039 TEST_F(TransferTest, VarDeclInDoWhile) { 2040 std::string Code = R"( 2041 void target(int *Foo) { 2042 do { 2043 int Bar = *Foo; 2044 } while (true); 2045 (void)0; 2046 /*[[p]]*/ 2047 } 2048 )"; 2049 runDataflow(Code, 2050 [](llvm::ArrayRef< 2051 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2052 Results, 2053 ASTContext &ASTCtx) { 2054 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2055 const Environment &Env = Results[0].second.Env; 2056 2057 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2058 ASSERT_THAT(FooDecl, NotNull()); 2059 2060 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2061 ASSERT_THAT(BarDecl, NotNull()); 2062 2063 const auto *FooVal = 2064 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2065 const auto *FooPointeeVal = 2066 cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc())); 2067 2068 const auto *BarVal = dyn_cast_or_null<IntegerValue>( 2069 Env.getValue(*BarDecl, SkipPast::None)); 2070 ASSERT_THAT(BarVal, NotNull()); 2071 2072 EXPECT_EQ(BarVal, FooPointeeVal); 2073 }); 2074 } 2075 2076 TEST_F(TransferTest, AggregateInitialization) { 2077 std::string BracesCode = R"( 2078 struct A { 2079 int Foo; 2080 }; 2081 2082 struct B { 2083 int Bar; 2084 A Baz; 2085 int Qux; 2086 }; 2087 2088 void target(int BarArg, int FooArg, int QuxArg) { 2089 B Quux{BarArg, {FooArg}, QuxArg}; 2090 /*[[p]]*/ 2091 } 2092 )"; 2093 std::string BraceEllisionCode = R"( 2094 struct A { 2095 int Foo; 2096 }; 2097 2098 struct B { 2099 int Bar; 2100 A Baz; 2101 int Qux; 2102 }; 2103 2104 void target(int BarArg, int FooArg, int QuxArg) { 2105 B Quux = {BarArg, FooArg, QuxArg}; 2106 /*[[p]]*/ 2107 } 2108 )"; 2109 for (const std::string &Code : {BracesCode, BraceEllisionCode}) { 2110 runDataflow( 2111 Code, [](llvm::ArrayRef< 2112 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2113 Results, 2114 ASTContext &ASTCtx) { 2115 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2116 const Environment &Env = Results[0].second.Env; 2117 2118 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2119 ASSERT_THAT(FooDecl, NotNull()); 2120 2121 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2122 ASSERT_THAT(BarDecl, NotNull()); 2123 2124 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2125 ASSERT_THAT(BazDecl, NotNull()); 2126 2127 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2128 ASSERT_THAT(QuxDecl, NotNull()); 2129 2130 const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg"); 2131 ASSERT_THAT(FooArgDecl, NotNull()); 2132 2133 const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg"); 2134 ASSERT_THAT(BarArgDecl, NotNull()); 2135 2136 const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg"); 2137 ASSERT_THAT(QuxArgDecl, NotNull()); 2138 2139 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 2140 ASSERT_THAT(QuuxDecl, NotNull()); 2141 2142 const auto *FooArgVal = 2143 cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None)); 2144 const auto *BarArgVal = 2145 cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None)); 2146 const auto *QuxArgVal = 2147 cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None)); 2148 2149 const auto *QuuxVal = 2150 cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None)); 2151 ASSERT_THAT(QuuxVal, NotNull()); 2152 2153 const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl)); 2154 ASSERT_THAT(BazVal, NotNull()); 2155 2156 EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal); 2157 EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal); 2158 EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal); 2159 }); 2160 } 2161 } 2162 2163 TEST_F(TransferTest, AssignToUnionMember) { 2164 std::string Code = R"( 2165 union A { 2166 int Foo; 2167 }; 2168 2169 void target(int Bar) { 2170 A Baz; 2171 Baz.Foo = Bar; 2172 // [[p]] 2173 } 2174 )"; 2175 runDataflow(Code, 2176 [](llvm::ArrayRef< 2177 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2178 Results, 2179 ASTContext &ASTCtx) { 2180 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2181 const Environment &Env = Results[0].second.Env; 2182 2183 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2184 ASSERT_THAT(BazDecl, NotNull()); 2185 ASSERT_TRUE(BazDecl->getType()->isUnionType()); 2186 2187 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>( 2188 Env.getStorageLocation(*BazDecl, SkipPast::None)); 2189 ASSERT_THAT(BazLoc, NotNull()); 2190 2191 // FIXME: Add support for union types. 2192 EXPECT_THAT(Env.getValue(*BazLoc), IsNull()); 2193 }); 2194 } 2195 2196 TEST_F(TransferTest, AssignFromBoolLiteral) { 2197 std::string Code = R"( 2198 void target() { 2199 bool Foo = true; 2200 bool Bar = false; 2201 // [[p]] 2202 } 2203 )"; 2204 runDataflow(Code, 2205 [](llvm::ArrayRef< 2206 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2207 Results, 2208 ASTContext &ASTCtx) { 2209 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2210 const Environment &Env = Results[0].second.Env; 2211 2212 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2213 ASSERT_THAT(FooDecl, NotNull()); 2214 2215 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2216 Env.getValue(*FooDecl, SkipPast::None)); 2217 ASSERT_THAT(FooVal, NotNull()); 2218 2219 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2220 ASSERT_THAT(BarDecl, NotNull()); 2221 2222 const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>( 2223 Env.getValue(*BarDecl, SkipPast::None)); 2224 ASSERT_THAT(BarVal, NotNull()); 2225 2226 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true)); 2227 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false)); 2228 }); 2229 } 2230 2231 TEST_F(TransferTest, AssignFromCompositeBoolExpression) { 2232 { 2233 std::string Code = R"( 2234 void target(bool Foo, bool Bar, bool Qux) { 2235 bool Baz = (Foo) && (Bar || Qux); 2236 // [[p]] 2237 } 2238 )"; 2239 runDataflow( 2240 Code, [](llvm::ArrayRef< 2241 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2242 Results, 2243 ASTContext &ASTCtx) { 2244 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2245 const Environment &Env = Results[0].second.Env; 2246 2247 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2248 ASSERT_THAT(FooDecl, NotNull()); 2249 2250 const auto *FooVal = dyn_cast_or_null<BoolValue>( 2251 Env.getValue(*FooDecl, SkipPast::None)); 2252 ASSERT_THAT(FooVal, NotNull()); 2253 2254 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2255 ASSERT_THAT(BarDecl, NotNull()); 2256 2257 const auto *BarVal = dyn_cast_or_null<BoolValue>( 2258 Env.getValue(*BarDecl, SkipPast::None)); 2259 ASSERT_THAT(BarVal, NotNull()); 2260 2261 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2262 ASSERT_THAT(QuxDecl, NotNull()); 2263 2264 const auto *QuxVal = dyn_cast_or_null<BoolValue>( 2265 Env.getValue(*QuxDecl, SkipPast::None)); 2266 ASSERT_THAT(QuxVal, NotNull()); 2267 2268 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2269 ASSERT_THAT(BazDecl, NotNull()); 2270 2271 const auto *BazVal = dyn_cast_or_null<ConjunctionValue>( 2272 Env.getValue(*BazDecl, SkipPast::None)); 2273 ASSERT_THAT(BazVal, NotNull()); 2274 EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal); 2275 2276 const auto *BazRightSubValVal = 2277 cast<DisjunctionValue>(&BazVal->getRightSubValue()); 2278 EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal); 2279 EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal); 2280 }); 2281 } 2282 2283 { 2284 std::string Code = R"( 2285 void target(bool Foo, bool Bar, bool Qux) { 2286 bool Baz = (Foo && Qux) || (Bar); 2287 // [[p]] 2288 } 2289 )"; 2290 runDataflow( 2291 Code, [](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 *FooDecl = findValueDecl(ASTCtx, "Foo"); 2299 ASSERT_THAT(FooDecl, NotNull()); 2300 2301 const auto *FooVal = dyn_cast_or_null<BoolValue>( 2302 Env.getValue(*FooDecl, SkipPast::None)); 2303 ASSERT_THAT(FooVal, NotNull()); 2304 2305 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2306 ASSERT_THAT(BarDecl, NotNull()); 2307 2308 const auto *BarVal = dyn_cast_or_null<BoolValue>( 2309 Env.getValue(*BarDecl, SkipPast::None)); 2310 ASSERT_THAT(BarVal, NotNull()); 2311 2312 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2313 ASSERT_THAT(QuxDecl, NotNull()); 2314 2315 const auto *QuxVal = dyn_cast_or_null<BoolValue>( 2316 Env.getValue(*QuxDecl, SkipPast::None)); 2317 ASSERT_THAT(QuxVal, NotNull()); 2318 2319 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2320 ASSERT_THAT(BazDecl, NotNull()); 2321 2322 const auto *BazVal = dyn_cast_or_null<DisjunctionValue>( 2323 Env.getValue(*BazDecl, SkipPast::None)); 2324 ASSERT_THAT(BazVal, NotNull()); 2325 2326 const auto *BazLeftSubValVal = 2327 cast<ConjunctionValue>(&BazVal->getLeftSubValue()); 2328 EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal); 2329 EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal); 2330 2331 EXPECT_EQ(&BazVal->getRightSubValue(), BarVal); 2332 }); 2333 } 2334 } 2335 2336 TEST_F(TransferTest, AssignFromBoolNegation) { 2337 std::string Code = R"( 2338 void target() { 2339 bool Foo = true; 2340 bool Bar = !(Foo); 2341 // [[p]] 2342 } 2343 )"; 2344 runDataflow(Code, 2345 [](llvm::ArrayRef< 2346 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2347 Results, 2348 ASTContext &ASTCtx) { 2349 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2350 const Environment &Env = Results[0].second.Env; 2351 2352 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2353 ASSERT_THAT(FooDecl, NotNull()); 2354 2355 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2356 Env.getValue(*FooDecl, SkipPast::None)); 2357 ASSERT_THAT(FooVal, NotNull()); 2358 2359 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2360 ASSERT_THAT(BarDecl, NotNull()); 2361 2362 const auto *BarVal = dyn_cast_or_null<NegationValue>( 2363 Env.getValue(*BarDecl, SkipPast::None)); 2364 ASSERT_THAT(BarVal, NotNull()); 2365 2366 EXPECT_EQ(&BarVal->getSubVal(), FooVal); 2367 }); 2368 } 2369 2370 TEST_F(TransferTest, StaticIntSingleVarDecl) { 2371 std::string Code = R"( 2372 void target() { 2373 static int Foo; 2374 // [[p]] 2375 } 2376 )"; 2377 runDataflow(Code, 2378 [](llvm::ArrayRef< 2379 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2380 Results, 2381 ASTContext &ASTCtx) { 2382 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2383 const Environment &Env = Results[0].second.Env; 2384 2385 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2386 ASSERT_THAT(FooDecl, NotNull()); 2387 2388 const StorageLocation *FooLoc = 2389 Env.getStorageLocation(*FooDecl, SkipPast::None); 2390 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 2391 2392 const Value *FooVal = Env.getValue(*FooLoc); 2393 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 2394 }); 2395 } 2396 2397 TEST_F(TransferTest, StaticIntGroupVarDecl) { 2398 std::string Code = R"( 2399 void target() { 2400 static int Foo, Bar; 2401 (void)0; 2402 // [[p]] 2403 } 2404 )"; 2405 runDataflow(Code, 2406 [](llvm::ArrayRef< 2407 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2408 Results, 2409 ASTContext &ASTCtx) { 2410 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2411 const Environment &Env = Results[0].second.Env; 2412 2413 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2414 ASSERT_THAT(FooDecl, NotNull()); 2415 2416 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2417 ASSERT_THAT(BarDecl, NotNull()); 2418 2419 const StorageLocation *FooLoc = 2420 Env.getStorageLocation(*FooDecl, SkipPast::None); 2421 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 2422 2423 const StorageLocation *BarLoc = 2424 Env.getStorageLocation(*BarDecl, SkipPast::None); 2425 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 2426 2427 const Value *FooVal = Env.getValue(*FooLoc); 2428 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 2429 2430 const Value *BarVal = Env.getValue(*BarLoc); 2431 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 2432 2433 EXPECT_NE(FooVal, BarVal); 2434 }); 2435 } 2436 2437 TEST_F(TransferTest, GlobalIntVarDecl) { 2438 std::string Code = R"( 2439 static int Foo; 2440 2441 void target() { 2442 int Bar = Foo; 2443 int Baz = Foo; 2444 // [[p]] 2445 } 2446 )"; 2447 runDataflow(Code, 2448 [](llvm::ArrayRef< 2449 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2450 Results, 2451 ASTContext &ASTCtx) { 2452 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2453 const Environment &Env = Results[0].second.Env; 2454 2455 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2456 ASSERT_THAT(BarDecl, NotNull()); 2457 2458 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2459 ASSERT_THAT(BazDecl, NotNull()); 2460 2461 const Value *BarVal = 2462 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2463 const Value *BazVal = 2464 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2465 EXPECT_EQ(BarVal, BazVal); 2466 }); 2467 } 2468 2469 TEST_F(TransferTest, StaticMemberIntVarDecl) { 2470 std::string Code = R"( 2471 struct A { 2472 static int Foo; 2473 }; 2474 2475 void target(A a) { 2476 int Bar = a.Foo; 2477 int Baz = a.Foo; 2478 // [[p]] 2479 } 2480 )"; 2481 runDataflow(Code, 2482 [](llvm::ArrayRef< 2483 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2484 Results, 2485 ASTContext &ASTCtx) { 2486 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2487 const Environment &Env = Results[0].second.Env; 2488 2489 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2490 ASSERT_THAT(BarDecl, NotNull()); 2491 2492 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2493 ASSERT_THAT(BazDecl, NotNull()); 2494 2495 const Value *BarVal = 2496 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2497 const Value *BazVal = 2498 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2499 EXPECT_EQ(BarVal, BazVal); 2500 }); 2501 } 2502 2503 TEST_F(TransferTest, StaticMemberRefVarDecl) { 2504 std::string Code = R"( 2505 struct A { 2506 static int &Foo; 2507 }; 2508 2509 void target(A a) { 2510 int Bar = a.Foo; 2511 int Baz = a.Foo; 2512 // [[p]] 2513 } 2514 )"; 2515 runDataflow(Code, 2516 [](llvm::ArrayRef< 2517 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2518 Results, 2519 ASTContext &ASTCtx) { 2520 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2521 const Environment &Env = Results[0].second.Env; 2522 2523 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2524 ASSERT_THAT(BarDecl, NotNull()); 2525 2526 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2527 ASSERT_THAT(BazDecl, NotNull()); 2528 2529 const Value *BarVal = 2530 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2531 const Value *BazVal = 2532 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2533 EXPECT_EQ(BarVal, BazVal); 2534 }); 2535 } 2536 2537 TEST_F(TransferTest, AssignMemberBeforeCopy) { 2538 std::string Code = R"( 2539 struct A { 2540 int Foo; 2541 }; 2542 2543 void target() { 2544 A A1; 2545 A A2; 2546 int Bar; 2547 A1.Foo = Bar; 2548 A2 = A1; 2549 // [[p]] 2550 } 2551 )"; 2552 runDataflow(Code, 2553 [](llvm::ArrayRef< 2554 std::pair<std::string, DataflowAnalysisState<NoopLattice>>> 2555 Results, 2556 ASTContext &ASTCtx) { 2557 ASSERT_THAT(Results, ElementsAre(Pair("p", _))); 2558 const Environment &Env = Results[0].second.Env; 2559 2560 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2561 ASSERT_THAT(FooDecl, NotNull()); 2562 2563 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2564 ASSERT_THAT(BarDecl, NotNull()); 2565 2566 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); 2567 ASSERT_THAT(A1Decl, NotNull()); 2568 2569 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); 2570 ASSERT_THAT(A2Decl, NotNull()); 2571 2572 const auto *BarVal = 2573 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2574 2575 const auto *A2Val = 2576 cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None)); 2577 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal); 2578 }); 2579 } 2580 2581 } // namespace 2582