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