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