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 "TestingSupport.h" 10 #include "clang/AST/ASTContext.h" 11 #include "clang/AST/Decl.h" 12 #include "clang/ASTMatchers/ASTMatchers.h" 13 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" 14 #include "clang/Analysis/FlowSensitive/NoopAnalysis.h" 15 #include "clang/Analysis/FlowSensitive/StorageLocation.h" 16 #include "clang/Analysis/FlowSensitive/Value.h" 17 #include "clang/Basic/LangStandard.h" 18 #include "llvm/ADT/ArrayRef.h" 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/Support/Casting.h" 21 #include "llvm/Testing/Support/Error.h" 22 #include "gmock/gmock.h" 23 #include "gtest/gtest.h" 24 #include <string> 25 #include <utility> 26 27 namespace { 28 29 using namespace clang; 30 using namespace dataflow; 31 using namespace test; 32 using ::testing::IsNull; 33 using ::testing::NotNull; 34 using ::testing::UnorderedElementsAre; 35 36 template <typename Matcher> 37 void runDataflow(llvm::StringRef Code, Matcher Match, 38 DataflowAnalysisOptions Options, 39 LangStandard::Kind Std = LangStandard::lang_cxx17, 40 llvm::StringRef TargetFun = "target") { 41 using ast_matchers::hasName; 42 ASSERT_THAT_ERROR( 43 checkDataflow<NoopAnalysis>( 44 AnalysisInputs<NoopAnalysis>(Code, hasName(TargetFun), 45 [Options](ASTContext &C, Environment &) { 46 return NoopAnalysis(C, Options); 47 }) 48 .withASTBuildArgs( 49 {"-fsyntax-only", "-fno-delayed-template-parsing", 50 "-std=" + 51 std::string(LangStandard::getLangStandardForKind(Std) 52 .getName())}), 53 /*VerifyResults=*/ 54 [&Match](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> 55 &Results, 56 const AnalysisOutputs &AO) { Match(Results, AO.ASTCtx); }), 57 llvm::Succeeded()); 58 } 59 60 template <typename Matcher> 61 void runDataflow(llvm::StringRef Code, Matcher Match, 62 LangStandard::Kind Std = LangStandard::lang_cxx17, 63 bool ApplyBuiltinTransfer = true, 64 llvm::StringRef TargetFun = "target") { 65 runDataflow(Code, std::move(Match), 66 {ApplyBuiltinTransfer ? TransferOptions{} 67 : llvm::Optional<TransferOptions>()}, 68 Std, TargetFun); 69 } 70 71 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) { 72 std::string Code = R"( 73 void target() { 74 int Foo; 75 // [[p]] 76 } 77 )"; 78 runDataflow( 79 Code, 80 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 81 ASTContext &ASTCtx) { 82 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 83 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 84 85 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 86 ASSERT_THAT(FooDecl, NotNull()); 87 88 EXPECT_EQ(Env.getStorageLocation(*FooDecl, SkipPast::None), nullptr); 89 }, 90 LangStandard::lang_cxx17, 91 /*ApplyBuiltinTransfer=*/false); 92 } 93 94 TEST(TransferTest, BoolVarDecl) { 95 std::string Code = R"( 96 void target() { 97 bool Foo; 98 // [[p]] 99 } 100 )"; 101 runDataflow( 102 Code, 103 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 104 ASTContext &ASTCtx) { 105 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 106 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 107 108 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 109 ASSERT_THAT(FooDecl, NotNull()); 110 111 const StorageLocation *FooLoc = 112 Env.getStorageLocation(*FooDecl, SkipPast::None); 113 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 114 115 const Value *FooVal = Env.getValue(*FooLoc); 116 EXPECT_TRUE(isa_and_nonnull<BoolValue>(FooVal)); 117 }); 118 } 119 120 TEST(TransferTest, IntVarDecl) { 121 std::string Code = R"( 122 void target() { 123 int Foo; 124 // [[p]] 125 } 126 )"; 127 runDataflow( 128 Code, 129 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 130 ASTContext &ASTCtx) { 131 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 132 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 133 134 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 135 ASSERT_THAT(FooDecl, NotNull()); 136 137 const StorageLocation *FooLoc = 138 Env.getStorageLocation(*FooDecl, SkipPast::None); 139 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 140 141 const Value *FooVal = Env.getValue(*FooLoc); 142 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 143 }); 144 } 145 146 TEST(TransferTest, StructVarDecl) { 147 std::string Code = R"( 148 struct A { 149 int Bar; 150 }; 151 152 void target() { 153 A Foo; 154 // [[p]] 155 } 156 )"; 157 runDataflow( 158 Code, 159 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 160 ASTContext &ASTCtx) { 161 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 162 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 163 164 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 165 ASSERT_THAT(FooDecl, NotNull()); 166 167 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 168 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 169 170 FieldDecl *BarDecl = nullptr; 171 for (FieldDecl *Field : FooFields) { 172 if (Field->getNameAsString() == "Bar") { 173 BarDecl = Field; 174 } else { 175 FAIL() << "Unexpected field: " << Field->getNameAsString(); 176 } 177 } 178 ASSERT_THAT(BarDecl, NotNull()); 179 180 const auto *FooLoc = cast<AggregateStorageLocation>( 181 Env.getStorageLocation(*FooDecl, SkipPast::None)); 182 const auto *BarLoc = 183 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 184 185 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 186 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 187 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 188 }); 189 } 190 191 TEST(TransferTest, StructVarDeclWithInit) { 192 std::string Code = R"( 193 struct A { 194 int Bar; 195 }; 196 197 A Gen(); 198 199 void target() { 200 A Foo = Gen(); 201 // [[p]] 202 } 203 )"; 204 runDataflow( 205 Code, 206 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 207 ASTContext &ASTCtx) { 208 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 209 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 210 211 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 212 ASSERT_THAT(FooDecl, NotNull()); 213 214 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 215 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 216 217 FieldDecl *BarDecl = nullptr; 218 for (FieldDecl *Field : FooFields) { 219 if (Field->getNameAsString() == "Bar") { 220 BarDecl = Field; 221 } else { 222 FAIL() << "Unexpected field: " << Field->getNameAsString(); 223 } 224 } 225 ASSERT_THAT(BarDecl, NotNull()); 226 227 const auto *FooLoc = cast<AggregateStorageLocation>( 228 Env.getStorageLocation(*FooDecl, SkipPast::None)); 229 const auto *BarLoc = 230 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 231 232 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 233 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 234 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 235 }); 236 } 237 238 TEST(TransferTest, ClassVarDecl) { 239 std::string Code = R"( 240 class A { 241 int Bar; 242 }; 243 244 void target() { 245 A Foo; 246 // [[p]] 247 } 248 )"; 249 runDataflow( 250 Code, 251 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 252 ASTContext &ASTCtx) { 253 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 254 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 255 256 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 257 ASSERT_THAT(FooDecl, NotNull()); 258 259 ASSERT_TRUE(FooDecl->getType()->isClassType()); 260 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 261 262 FieldDecl *BarDecl = nullptr; 263 for (FieldDecl *Field : FooFields) { 264 if (Field->getNameAsString() == "Bar") { 265 BarDecl = Field; 266 } else { 267 FAIL() << "Unexpected field: " << Field->getNameAsString(); 268 } 269 } 270 ASSERT_THAT(BarDecl, NotNull()); 271 272 const auto *FooLoc = cast<AggregateStorageLocation>( 273 Env.getStorageLocation(*FooDecl, SkipPast::None)); 274 const auto *BarLoc = 275 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 276 277 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 278 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 279 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 280 }); 281 } 282 283 TEST(TransferTest, ReferenceVarDecl) { 284 std::string Code = R"( 285 struct A {}; 286 287 A &getA(); 288 289 void target() { 290 A &Foo = getA(); 291 // [[p]] 292 } 293 )"; 294 runDataflow( 295 Code, 296 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 297 ASTContext &ASTCtx) { 298 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 299 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 300 301 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 302 ASSERT_THAT(FooDecl, NotNull()); 303 304 const StorageLocation *FooLoc = 305 Env.getStorageLocation(*FooDecl, SkipPast::None); 306 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 307 308 const ReferenceValue *FooVal = 309 cast<ReferenceValue>(Env.getValue(*FooLoc)); 310 const StorageLocation &FooReferentLoc = FooVal->getReferentLoc(); 311 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooReferentLoc)); 312 313 const Value *FooReferentVal = Env.getValue(FooReferentLoc); 314 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal)); 315 }); 316 } 317 318 TEST(TransferTest, SelfReferentialReferenceVarDecl) { 319 std::string Code = R"( 320 struct A; 321 322 struct B {}; 323 324 struct C { 325 A &FooRef; 326 A *FooPtr; 327 B &BazRef; 328 B *BazPtr; 329 }; 330 331 struct A { 332 C &Bar; 333 }; 334 335 A &getA(); 336 337 void target() { 338 A &Foo = getA(); 339 // [[p]] 340 } 341 )"; 342 runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> 343 &Results, 344 ASTContext &ASTCtx) { 345 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 346 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 347 348 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 349 ASSERT_THAT(FooDecl, NotNull()); 350 351 ASSERT_TRUE(FooDecl->getType()->isReferenceType()); 352 ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType()); 353 const auto FooFields = 354 FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields(); 355 356 FieldDecl *BarDecl = nullptr; 357 for (FieldDecl *Field : FooFields) { 358 if (Field->getNameAsString() == "Bar") { 359 BarDecl = Field; 360 } else { 361 FAIL() << "Unexpected field: " << Field->getNameAsString(); 362 } 363 } 364 ASSERT_THAT(BarDecl, NotNull()); 365 366 ASSERT_TRUE(BarDecl->getType()->isReferenceType()); 367 ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType()); 368 const auto BarFields = 369 BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields(); 370 371 FieldDecl *FooRefDecl = nullptr; 372 FieldDecl *FooPtrDecl = nullptr; 373 FieldDecl *BazRefDecl = nullptr; 374 FieldDecl *BazPtrDecl = nullptr; 375 for (FieldDecl *Field : BarFields) { 376 if (Field->getNameAsString() == "FooRef") { 377 FooRefDecl = Field; 378 } else if (Field->getNameAsString() == "FooPtr") { 379 FooPtrDecl = Field; 380 } else if (Field->getNameAsString() == "BazRef") { 381 BazRefDecl = Field; 382 } else if (Field->getNameAsString() == "BazPtr") { 383 BazPtrDecl = Field; 384 } else { 385 FAIL() << "Unexpected field: " << Field->getNameAsString(); 386 } 387 } 388 ASSERT_THAT(FooRefDecl, NotNull()); 389 ASSERT_THAT(FooPtrDecl, NotNull()); 390 ASSERT_THAT(BazRefDecl, NotNull()); 391 ASSERT_THAT(BazPtrDecl, NotNull()); 392 393 const auto *FooLoc = cast<ScalarStorageLocation>( 394 Env.getStorageLocation(*FooDecl, SkipPast::None)); 395 const auto *FooVal = cast<ReferenceValue>(Env.getValue(*FooLoc)); 396 const auto *FooReferentVal = 397 cast<StructValue>(Env.getValue(FooVal->getReferentLoc())); 398 399 const auto *BarVal = 400 cast<ReferenceValue>(FooReferentVal->getChild(*BarDecl)); 401 const auto *BarReferentVal = 402 cast<StructValue>(Env.getValue(BarVal->getReferentLoc())); 403 404 const auto *FooRefVal = 405 cast<ReferenceValue>(BarReferentVal->getChild(*FooRefDecl)); 406 const StorageLocation &FooReferentLoc = FooRefVal->getReferentLoc(); 407 EXPECT_THAT(Env.getValue(FooReferentLoc), IsNull()); 408 409 const auto *FooPtrVal = 410 cast<PointerValue>(BarReferentVal->getChild(*FooPtrDecl)); 411 const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc(); 412 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull()); 413 414 const auto *BazRefVal = 415 cast<ReferenceValue>(BarReferentVal->getChild(*BazRefDecl)); 416 const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc(); 417 EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull()); 418 419 const auto *BazPtrVal = 420 cast<PointerValue>(BarReferentVal->getChild(*BazPtrDecl)); 421 const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc(); 422 EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); 423 }); 424 } 425 426 TEST(TransferTest, PointerVarDecl) { 427 std::string Code = R"( 428 struct A {}; 429 430 A *getA(); 431 432 void target() { 433 A *Foo = getA(); 434 // [[p]] 435 } 436 )"; 437 runDataflow( 438 Code, 439 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 440 ASTContext &ASTCtx) { 441 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 442 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 443 444 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 445 ASSERT_THAT(FooDecl, NotNull()); 446 447 const StorageLocation *FooLoc = 448 Env.getStorageLocation(*FooDecl, SkipPast::None); 449 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 450 451 const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 452 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 453 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 454 455 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 456 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 457 }); 458 } 459 460 TEST(TransferTest, SelfReferentialPointerVarDecl) { 461 std::string Code = R"( 462 struct A; 463 464 struct B {}; 465 466 struct C { 467 A &FooRef; 468 A *FooPtr; 469 B &BazRef; 470 B *BazPtr; 471 }; 472 473 struct A { 474 C *Bar; 475 }; 476 477 A *getA(); 478 479 void target() { 480 A *Foo = getA(); 481 // [[p]] 482 } 483 )"; 484 runDataflow( 485 Code, 486 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 487 ASTContext &ASTCtx) { 488 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 489 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 490 491 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 492 ASSERT_THAT(FooDecl, NotNull()); 493 494 ASSERT_TRUE(FooDecl->getType()->isPointerType()); 495 ASSERT_TRUE(FooDecl->getType() 496 ->getAs<PointerType>() 497 ->getPointeeType() 498 ->isStructureType()); 499 const auto FooFields = FooDecl->getType() 500 ->getAs<PointerType>() 501 ->getPointeeType() 502 ->getAsRecordDecl() 503 ->fields(); 504 505 FieldDecl *BarDecl = nullptr; 506 for (FieldDecl *Field : FooFields) { 507 if (Field->getNameAsString() == "Bar") { 508 BarDecl = Field; 509 } else { 510 FAIL() << "Unexpected field: " << Field->getNameAsString(); 511 } 512 } 513 ASSERT_THAT(BarDecl, NotNull()); 514 515 ASSERT_TRUE(BarDecl->getType()->isPointerType()); 516 ASSERT_TRUE(BarDecl->getType() 517 ->getAs<PointerType>() 518 ->getPointeeType() 519 ->isStructureType()); 520 const auto BarFields = BarDecl->getType() 521 ->getAs<PointerType>() 522 ->getPointeeType() 523 ->getAsRecordDecl() 524 ->fields(); 525 526 FieldDecl *FooRefDecl = nullptr; 527 FieldDecl *FooPtrDecl = nullptr; 528 FieldDecl *BazRefDecl = nullptr; 529 FieldDecl *BazPtrDecl = nullptr; 530 for (FieldDecl *Field : BarFields) { 531 if (Field->getNameAsString() == "FooRef") { 532 FooRefDecl = Field; 533 } else if (Field->getNameAsString() == "FooPtr") { 534 FooPtrDecl = Field; 535 } else if (Field->getNameAsString() == "BazRef") { 536 BazRefDecl = Field; 537 } else if (Field->getNameAsString() == "BazPtr") { 538 BazPtrDecl = Field; 539 } else { 540 FAIL() << "Unexpected field: " << Field->getNameAsString(); 541 } 542 } 543 ASSERT_THAT(FooRefDecl, NotNull()); 544 ASSERT_THAT(FooPtrDecl, NotNull()); 545 ASSERT_THAT(BazRefDecl, NotNull()); 546 ASSERT_THAT(BazPtrDecl, NotNull()); 547 548 const auto *FooLoc = cast<ScalarStorageLocation>( 549 Env.getStorageLocation(*FooDecl, SkipPast::None)); 550 const auto *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 551 const auto *FooPointeeVal = 552 cast<StructValue>(Env.getValue(FooVal->getPointeeLoc())); 553 554 const auto *BarVal = 555 cast<PointerValue>(FooPointeeVal->getChild(*BarDecl)); 556 const auto *BarPointeeVal = 557 cast<StructValue>(Env.getValue(BarVal->getPointeeLoc())); 558 559 const auto *FooRefVal = 560 cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl)); 561 const StorageLocation &FooReferentLoc = FooRefVal->getReferentLoc(); 562 EXPECT_THAT(Env.getValue(FooReferentLoc), IsNull()); 563 564 const auto *FooPtrVal = 565 cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl)); 566 const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc(); 567 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull()); 568 569 const auto *BazRefVal = 570 cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl)); 571 const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc(); 572 EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull()); 573 574 const auto *BazPtrVal = 575 cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl)); 576 const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc(); 577 EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); 578 }); 579 } 580 581 TEST(TransferTest, MultipleVarsDecl) { 582 std::string Code = R"( 583 void target() { 584 int Foo, Bar; 585 (void)0; 586 // [[p]] 587 } 588 )"; 589 runDataflow( 590 Code, 591 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 592 ASTContext &ASTCtx) { 593 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 594 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 595 596 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 597 ASSERT_THAT(FooDecl, NotNull()); 598 599 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 600 ASSERT_THAT(BarDecl, NotNull()); 601 602 const StorageLocation *FooLoc = 603 Env.getStorageLocation(*FooDecl, SkipPast::None); 604 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 605 606 const StorageLocation *BarLoc = 607 Env.getStorageLocation(*BarDecl, SkipPast::None); 608 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 609 610 const Value *FooVal = Env.getValue(*FooLoc); 611 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 612 613 const Value *BarVal = Env.getValue(*BarLoc); 614 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 615 }); 616 } 617 618 TEST(TransferTest, JoinVarDecl) { 619 std::string Code = R"( 620 void target(bool B) { 621 int Foo; 622 // [[p1]] 623 if (B) { 624 int Bar; 625 // [[p2]] 626 } else { 627 int Baz; 628 // [[p3]] 629 } 630 (void)0; 631 // [[p4]] 632 } 633 )"; 634 runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> 635 &Results, 636 ASTContext &ASTCtx) { 637 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2", "p3", "p4")); 638 639 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 640 ASSERT_THAT(FooDecl, NotNull()); 641 642 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 643 ASSERT_THAT(BarDecl, NotNull()); 644 645 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 646 ASSERT_THAT(BazDecl, NotNull()); 647 648 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 649 650 const StorageLocation *FooLoc = 651 Env1.getStorageLocation(*FooDecl, SkipPast::None); 652 EXPECT_THAT(FooLoc, NotNull()); 653 EXPECT_THAT(Env1.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 654 EXPECT_THAT(Env1.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 655 656 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 657 EXPECT_EQ(Env2.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 658 EXPECT_THAT(Env2.getStorageLocation(*BarDecl, SkipPast::None), NotNull()); 659 EXPECT_THAT(Env2.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 660 661 const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3"); 662 EXPECT_EQ(Env3.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 663 EXPECT_THAT(Env3.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 664 EXPECT_THAT(Env3.getStorageLocation(*BazDecl, SkipPast::None), NotNull()); 665 666 const Environment &Env4 = getEnvironmentAtAnnotation(Results, "p4"); 667 EXPECT_EQ(Env4.getStorageLocation(*FooDecl, SkipPast::None), FooLoc); 668 EXPECT_THAT(Env4.getStorageLocation(*BarDecl, SkipPast::None), IsNull()); 669 EXPECT_THAT(Env4.getStorageLocation(*BazDecl, SkipPast::None), IsNull()); 670 }); 671 } 672 673 TEST(TransferTest, BinaryOperatorAssign) { 674 std::string Code = R"( 675 void target() { 676 int Foo; 677 int Bar; 678 (Bar) = (Foo); 679 // [[p]] 680 } 681 )"; 682 runDataflow( 683 Code, 684 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 685 ASTContext &ASTCtx) { 686 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 687 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 688 689 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 690 ASSERT_THAT(FooDecl, NotNull()); 691 692 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 693 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 694 695 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 696 ASSERT_THAT(BarDecl, NotNull()); 697 698 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 699 }); 700 } 701 702 TEST(TransferTest, VarDeclInitAssign) { 703 std::string Code = R"( 704 void target() { 705 int Foo; 706 int Bar = Foo; 707 // [[p]] 708 } 709 )"; 710 runDataflow( 711 Code, 712 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 713 ASTContext &ASTCtx) { 714 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 715 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 716 717 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 718 ASSERT_THAT(FooDecl, NotNull()); 719 720 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 721 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 722 723 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 724 ASSERT_THAT(BarDecl, NotNull()); 725 726 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 727 }); 728 } 729 730 TEST(TransferTest, VarDeclInitAssignChained) { 731 std::string Code = R"( 732 void target() { 733 int Foo; 734 int Bar; 735 int Baz = (Bar = Foo); 736 // [[p]] 737 } 738 )"; 739 runDataflow( 740 Code, 741 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 742 ASTContext &ASTCtx) { 743 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 744 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 745 746 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 747 ASSERT_THAT(FooDecl, NotNull()); 748 749 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 750 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 751 752 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 753 ASSERT_THAT(BarDecl, NotNull()); 754 755 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 756 ASSERT_THAT(BazDecl, NotNull()); 757 758 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal); 759 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal); 760 }); 761 } 762 763 TEST(TransferTest, VarDeclInitAssignPtrDeref) { 764 std::string Code = R"( 765 void target() { 766 int Foo; 767 int *Bar; 768 *(Bar) = Foo; 769 int Baz = *(Bar); 770 // [[p]] 771 } 772 )"; 773 runDataflow( 774 Code, 775 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 776 ASTContext &ASTCtx) { 777 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 778 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 779 780 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 781 ASSERT_THAT(FooDecl, NotNull()); 782 783 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None); 784 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 785 786 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 787 ASSERT_THAT(BarDecl, NotNull()); 788 789 const auto *BarVal = 790 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 791 EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal); 792 793 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 794 ASSERT_THAT(BazDecl, NotNull()); 795 796 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal); 797 }); 798 } 799 800 TEST(TransferTest, AssignToAndFromReference) { 801 std::string Code = R"( 802 void target() { 803 int Foo; 804 int Bar; 805 int &Baz = Foo; 806 // [[p1]] 807 Baz = Bar; 808 int Qux = Baz; 809 int &Quux = Baz; 810 // [[p2]] 811 } 812 )"; 813 runDataflow( 814 Code, 815 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 816 ASTContext &ASTCtx) { 817 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 818 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 819 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 820 821 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 822 ASSERT_THAT(FooDecl, NotNull()); 823 824 const Value *FooVal = Env1.getValue(*FooDecl, SkipPast::None); 825 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 826 827 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 828 ASSERT_THAT(BarDecl, NotNull()); 829 830 const Value *BarVal = Env1.getValue(*BarDecl, SkipPast::None); 831 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 832 833 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 834 ASSERT_THAT(BazDecl, NotNull()); 835 836 EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), FooVal); 837 838 EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BarVal); 839 EXPECT_EQ(Env2.getValue(*FooDecl, SkipPast::None), BarVal); 840 841 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 842 ASSERT_THAT(QuxDecl, NotNull()); 843 EXPECT_EQ(Env2.getValue(*QuxDecl, SkipPast::None), BarVal); 844 845 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 846 ASSERT_THAT(QuuxDecl, NotNull()); 847 EXPECT_EQ(Env2.getValue(*QuuxDecl, SkipPast::Reference), BarVal); 848 }); 849 } 850 851 TEST(TransferTest, MultipleParamDecls) { 852 std::string Code = R"( 853 void target(int Foo, int Bar) { 854 (void)0; 855 // [[p]] 856 } 857 )"; 858 runDataflow( 859 Code, 860 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 861 ASTContext &ASTCtx) { 862 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 863 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 864 865 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 866 ASSERT_THAT(FooDecl, NotNull()); 867 868 const StorageLocation *FooLoc = 869 Env.getStorageLocation(*FooDecl, SkipPast::None); 870 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 871 872 const Value *FooVal = Env.getValue(*FooLoc); 873 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 874 875 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 876 ASSERT_THAT(BarDecl, NotNull()); 877 878 const StorageLocation *BarLoc = 879 Env.getStorageLocation(*BarDecl, SkipPast::None); 880 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 881 882 const Value *BarVal = Env.getValue(*BarLoc); 883 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 884 }); 885 } 886 887 TEST(TransferTest, StructParamDecl) { 888 std::string Code = R"( 889 struct A { 890 int Bar; 891 }; 892 893 void target(A Foo) { 894 (void)0; 895 // [[p]] 896 } 897 )"; 898 runDataflow( 899 Code, 900 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 901 ASTContext &ASTCtx) { 902 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 903 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 904 905 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 906 ASSERT_THAT(FooDecl, NotNull()); 907 908 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 909 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 910 911 FieldDecl *BarDecl = nullptr; 912 for (FieldDecl *Field : FooFields) { 913 if (Field->getNameAsString() == "Bar") { 914 BarDecl = Field; 915 } else { 916 FAIL() << "Unexpected field: " << Field->getNameAsString(); 917 } 918 } 919 ASSERT_THAT(BarDecl, NotNull()); 920 921 const auto *FooLoc = cast<AggregateStorageLocation>( 922 Env.getStorageLocation(*FooDecl, SkipPast::None)); 923 const auto *BarLoc = 924 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 925 926 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 927 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 928 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 929 }); 930 } 931 932 TEST(TransferTest, ReferenceParamDecl) { 933 std::string Code = R"( 934 struct A {}; 935 936 void target(A &Foo) { 937 (void)0; 938 // [[p]] 939 } 940 )"; 941 runDataflow( 942 Code, 943 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 944 ASTContext &ASTCtx) { 945 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 946 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 947 948 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 949 ASSERT_THAT(FooDecl, NotNull()); 950 951 const StorageLocation *FooLoc = 952 Env.getStorageLocation(*FooDecl, SkipPast::None); 953 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 954 955 const ReferenceValue *FooVal = 956 dyn_cast<ReferenceValue>(Env.getValue(*FooLoc)); 957 ASSERT_THAT(FooVal, NotNull()); 958 959 const StorageLocation &FooReferentLoc = FooVal->getReferentLoc(); 960 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooReferentLoc)); 961 962 const Value *FooReferentVal = Env.getValue(FooReferentLoc); 963 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal)); 964 }); 965 } 966 967 TEST(TransferTest, PointerParamDecl) { 968 std::string Code = R"( 969 struct A {}; 970 971 void target(A *Foo) { 972 (void)0; 973 // [[p]] 974 } 975 )"; 976 runDataflow( 977 Code, 978 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 979 ASTContext &ASTCtx) { 980 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 981 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 982 983 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 984 ASSERT_THAT(FooDecl, NotNull()); 985 986 const StorageLocation *FooLoc = 987 Env.getStorageLocation(*FooDecl, SkipPast::None); 988 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 989 990 const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 991 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 992 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 993 994 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 995 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 996 }); 997 } 998 999 TEST(TransferTest, StructMember) { 1000 std::string Code = R"( 1001 struct A { 1002 int Bar; 1003 }; 1004 1005 void target(A Foo) { 1006 int Baz = Foo.Bar; 1007 // [[p]] 1008 } 1009 )"; 1010 runDataflow( 1011 Code, 1012 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1013 ASTContext &ASTCtx) { 1014 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1015 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1016 1017 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1018 ASSERT_THAT(FooDecl, NotNull()); 1019 1020 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1021 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1022 1023 FieldDecl *BarDecl = nullptr; 1024 for (FieldDecl *Field : FooFields) { 1025 if (Field->getNameAsString() == "Bar") { 1026 BarDecl = Field; 1027 } else { 1028 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1029 } 1030 } 1031 ASSERT_THAT(BarDecl, NotNull()); 1032 1033 const auto *FooLoc = cast<AggregateStorageLocation>( 1034 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1035 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1036 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1037 1038 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1039 ASSERT_THAT(BazDecl, NotNull()); 1040 1041 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal); 1042 }); 1043 } 1044 1045 TEST(TransferTest, DerivedBaseMemberClass) { 1046 std::string Code = R"( 1047 class A { 1048 int ADefault; 1049 protected: 1050 int AProtected; 1051 private: 1052 int APrivate; 1053 public: 1054 int APublic; 1055 }; 1056 1057 class B : public A { 1058 int BDefault; 1059 protected: 1060 int BProtected; 1061 private: 1062 int BPrivate; 1063 }; 1064 1065 void target() { 1066 B Foo; 1067 // [[p]] 1068 } 1069 )"; 1070 runDataflow( 1071 Code, 1072 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1073 ASTContext &ASTCtx) { 1074 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1075 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1076 1077 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1078 ASSERT_THAT(FooDecl, NotNull()); 1079 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1080 1081 // Derived-class fields. 1082 const FieldDecl *BDefaultDecl = nullptr; 1083 const FieldDecl *BProtectedDecl = nullptr; 1084 const FieldDecl *BPrivateDecl = nullptr; 1085 for (const FieldDecl *Field : 1086 FooDecl->getType()->getAsRecordDecl()->fields()) { 1087 if (Field->getNameAsString() == "BDefault") { 1088 BDefaultDecl = Field; 1089 } else if (Field->getNameAsString() == "BProtected") { 1090 BProtectedDecl = Field; 1091 } else if (Field->getNameAsString() == "BPrivate") { 1092 BPrivateDecl = Field; 1093 } else { 1094 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1095 } 1096 } 1097 ASSERT_THAT(BDefaultDecl, NotNull()); 1098 ASSERT_THAT(BProtectedDecl, NotNull()); 1099 ASSERT_THAT(BPrivateDecl, NotNull()); 1100 1101 // Base-class fields. 1102 const FieldDecl *ADefaultDecl = nullptr; 1103 const FieldDecl *APrivateDecl = nullptr; 1104 const FieldDecl *AProtectedDecl = nullptr; 1105 const FieldDecl *APublicDecl = nullptr; 1106 for (const clang::CXXBaseSpecifier &Base : 1107 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1108 QualType BaseType = Base.getType(); 1109 ASSERT_TRUE(BaseType->isRecordType()); 1110 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1111 if (Field->getNameAsString() == "ADefault") { 1112 ADefaultDecl = Field; 1113 } else if (Field->getNameAsString() == "AProtected") { 1114 AProtectedDecl = Field; 1115 } else if (Field->getNameAsString() == "APrivate") { 1116 APrivateDecl = Field; 1117 } else if (Field->getNameAsString() == "APublic") { 1118 APublicDecl = Field; 1119 } else { 1120 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1121 } 1122 } 1123 } 1124 ASSERT_THAT(ADefaultDecl, NotNull()); 1125 ASSERT_THAT(AProtectedDecl, NotNull()); 1126 ASSERT_THAT(APrivateDecl, NotNull()); 1127 ASSERT_THAT(APublicDecl, NotNull()); 1128 1129 const auto &FooLoc = *cast<AggregateStorageLocation>( 1130 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1131 const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc)); 1132 1133 // Note: we can't test presence of children in `FooLoc`, because 1134 // `getChild` requires its argument be present (or fails an assert). So, 1135 // we limit to testing presence in `FooVal` and coherence between the 1136 // two. 1137 1138 // Base-class fields. 1139 EXPECT_THAT(FooVal.getChild(*ADefaultDecl), NotNull()); 1140 EXPECT_THAT(FooVal.getChild(*APrivateDecl), NotNull()); 1141 1142 EXPECT_THAT(FooVal.getChild(*AProtectedDecl), NotNull()); 1143 EXPECT_EQ(Env.getValue(FooLoc.getChild(*APublicDecl)), 1144 FooVal.getChild(*APublicDecl)); 1145 EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull()); 1146 EXPECT_EQ(Env.getValue(FooLoc.getChild(*AProtectedDecl)), 1147 FooVal.getChild(*AProtectedDecl)); 1148 1149 // Derived-class fields. 1150 EXPECT_THAT(FooVal.getChild(*BDefaultDecl), NotNull()); 1151 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BDefaultDecl)), 1152 FooVal.getChild(*BDefaultDecl)); 1153 EXPECT_THAT(FooVal.getChild(*BProtectedDecl), NotNull()); 1154 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BProtectedDecl)), 1155 FooVal.getChild(*BProtectedDecl)); 1156 EXPECT_THAT(FooVal.getChild(*BPrivateDecl), NotNull()); 1157 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BPrivateDecl)), 1158 FooVal.getChild(*BPrivateDecl)); 1159 }); 1160 } 1161 1162 static void derivedBaseMemberExpectations( 1163 const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1164 ASTContext &ASTCtx) { 1165 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1166 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1167 1168 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1169 ASSERT_THAT(FooDecl, NotNull()); 1170 1171 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1172 const FieldDecl *BarDecl = nullptr; 1173 for (const clang::CXXBaseSpecifier &Base : 1174 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1175 QualType BaseType = Base.getType(); 1176 ASSERT_TRUE(BaseType->isStructureType()); 1177 1178 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1179 if (Field->getNameAsString() == "Bar") { 1180 BarDecl = Field; 1181 } else { 1182 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1183 } 1184 } 1185 } 1186 ASSERT_THAT(BarDecl, NotNull()); 1187 1188 const auto &FooLoc = *cast<AggregateStorageLocation>( 1189 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1190 const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc)); 1191 EXPECT_THAT(FooVal.getChild(*BarDecl), NotNull()); 1192 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BarDecl)), FooVal.getChild(*BarDecl)); 1193 } 1194 1195 TEST(TransferTest, DerivedBaseMemberStructDefault) { 1196 std::string Code = R"( 1197 struct A { 1198 int Bar; 1199 }; 1200 struct B : public A { 1201 }; 1202 1203 void target() { 1204 B Foo; 1205 // [[p]] 1206 } 1207 )"; 1208 runDataflow(Code, derivedBaseMemberExpectations); 1209 } 1210 1211 TEST(TransferTest, DerivedBaseMemberPrivateFriend) { 1212 // Include an access to `Foo.Bar` to verify the analysis doesn't crash on that 1213 // access. 1214 std::string Code = R"( 1215 struct A { 1216 private: 1217 friend void target(); 1218 int Bar; 1219 }; 1220 struct B : public A { 1221 }; 1222 1223 void target() { 1224 B Foo; 1225 (void)Foo.Bar; 1226 // [[p]] 1227 } 1228 )"; 1229 runDataflow(Code, derivedBaseMemberExpectations); 1230 } 1231 1232 TEST(TransferTest, ClassMember) { 1233 std::string Code = R"( 1234 class A { 1235 public: 1236 int Bar; 1237 }; 1238 1239 void target(A Foo) { 1240 int Baz = Foo.Bar; 1241 // [[p]] 1242 } 1243 )"; 1244 runDataflow( 1245 Code, 1246 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1247 ASTContext &ASTCtx) { 1248 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1249 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1250 1251 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1252 ASSERT_THAT(FooDecl, NotNull()); 1253 1254 ASSERT_TRUE(FooDecl->getType()->isClassType()); 1255 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1256 1257 FieldDecl *BarDecl = nullptr; 1258 for (FieldDecl *Field : FooFields) { 1259 if (Field->getNameAsString() == "Bar") { 1260 BarDecl = Field; 1261 } else { 1262 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1263 } 1264 } 1265 ASSERT_THAT(BarDecl, NotNull()); 1266 1267 const auto *FooLoc = cast<AggregateStorageLocation>( 1268 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1269 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1270 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1271 1272 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1273 ASSERT_THAT(BazDecl, NotNull()); 1274 1275 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal); 1276 }); 1277 } 1278 1279 TEST(TransferTest, BaseClassInitializer) { 1280 using ast_matchers::cxxConstructorDecl; 1281 using ast_matchers::hasName; 1282 using ast_matchers::ofClass; 1283 1284 std::string Code = R"( 1285 class A { 1286 public: 1287 A(int I) : Bar(I) {} 1288 int Bar; 1289 }; 1290 1291 class B : public A { 1292 public: 1293 B(int I) : A(I) { 1294 (void)0; 1295 // [[p]] 1296 } 1297 }; 1298 )"; 1299 ASSERT_THAT_ERROR( 1300 checkDataflow<NoopAnalysis>( 1301 AnalysisInputs<NoopAnalysis>( 1302 Code, cxxConstructorDecl(ofClass(hasName("B"))), 1303 [](ASTContext &C, Environment &) { 1304 return NoopAnalysis(C, /*ApplyBuiltinTransfer=*/true); 1305 }) 1306 .withASTBuildArgs( 1307 {"-fsyntax-only", "-fno-delayed-template-parsing", 1308 "-std=" + std::string(LangStandard::getLangStandardForKind( 1309 LangStandard::lang_cxx17) 1310 .getName())}), 1311 /*VerifyResults=*/ 1312 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1313 const AnalysisOutputs &) { 1314 // Regression test to verify that base-class initializers do not 1315 // trigger an assertion. If we add support for such initializers in 1316 // the future, we can expand this test to check more specific 1317 // properties. 1318 EXPECT_THAT(Results.keys(), UnorderedElementsAre("p")); 1319 }), 1320 llvm::Succeeded()); 1321 } 1322 1323 TEST(TransferTest, ReferenceMember) { 1324 std::string Code = R"( 1325 struct A { 1326 int &Bar; 1327 }; 1328 1329 void target(A Foo) { 1330 int Baz = Foo.Bar; 1331 // [[p]] 1332 } 1333 )"; 1334 runDataflow( 1335 Code, 1336 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1337 ASTContext &ASTCtx) { 1338 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1339 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1340 1341 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1342 ASSERT_THAT(FooDecl, NotNull()); 1343 1344 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1345 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1346 1347 FieldDecl *BarDecl = nullptr; 1348 for (FieldDecl *Field : FooFields) { 1349 if (Field->getNameAsString() == "Bar") { 1350 BarDecl = Field; 1351 } else { 1352 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1353 } 1354 } 1355 ASSERT_THAT(BarDecl, NotNull()); 1356 1357 const auto *FooLoc = cast<AggregateStorageLocation>( 1358 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1359 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1360 const auto *BarVal = cast<ReferenceValue>(FooVal->getChild(*BarDecl)); 1361 const auto *BarReferentVal = 1362 cast<IntegerValue>(Env.getValue(BarVal->getReferentLoc())); 1363 1364 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1365 ASSERT_THAT(BazDecl, NotNull()); 1366 1367 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarReferentVal); 1368 }); 1369 } 1370 1371 TEST(TransferTest, StructThisMember) { 1372 std::string Code = R"( 1373 struct A { 1374 int Bar; 1375 1376 struct B { 1377 int Baz; 1378 }; 1379 1380 B Qux; 1381 1382 void target() { 1383 int Foo = Bar; 1384 int Quux = Qux.Baz; 1385 // [[p]] 1386 } 1387 }; 1388 )"; 1389 runDataflow( 1390 Code, 1391 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1392 ASTContext &ASTCtx) { 1393 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1394 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1395 1396 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1397 Env.getThisPointeeStorageLocation()); 1398 ASSERT_THAT(ThisLoc, NotNull()); 1399 1400 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1401 ASSERT_THAT(BarDecl, NotNull()); 1402 1403 const auto *BarLoc = 1404 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1405 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1406 1407 const Value *BarVal = Env.getValue(*BarLoc); 1408 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1409 1410 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1411 ASSERT_THAT(FooDecl, NotNull()); 1412 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1413 1414 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1415 ASSERT_THAT(QuxDecl, NotNull()); 1416 1417 ASSERT_TRUE(QuxDecl->getType()->isStructureType()); 1418 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1419 1420 FieldDecl *BazDecl = nullptr; 1421 for (FieldDecl *Field : QuxFields) { 1422 if (Field->getNameAsString() == "Baz") { 1423 BazDecl = Field; 1424 } else { 1425 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1426 } 1427 } 1428 ASSERT_THAT(BazDecl, NotNull()); 1429 1430 const auto *QuxLoc = 1431 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1432 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1433 ASSERT_THAT(QuxVal, NotNull()); 1434 1435 const auto *BazLoc = 1436 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1437 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1438 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1439 1440 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1441 ASSERT_THAT(QuuxDecl, NotNull()); 1442 EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal); 1443 }); 1444 } 1445 1446 TEST(TransferTest, ClassThisMember) { 1447 std::string Code = R"( 1448 class A { 1449 int Bar; 1450 1451 class B { 1452 public: 1453 int Baz; 1454 }; 1455 1456 B Qux; 1457 1458 void target() { 1459 int Foo = Bar; 1460 int Quux = Qux.Baz; 1461 // [[p]] 1462 } 1463 }; 1464 )"; 1465 runDataflow( 1466 Code, 1467 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1468 ASTContext &ASTCtx) { 1469 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1470 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1471 1472 const auto *ThisLoc = 1473 cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation()); 1474 1475 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1476 ASSERT_THAT(BarDecl, NotNull()); 1477 1478 const auto *BarLoc = 1479 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1480 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1481 1482 const Value *BarVal = Env.getValue(*BarLoc); 1483 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1484 1485 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1486 ASSERT_THAT(FooDecl, NotNull()); 1487 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1488 1489 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1490 ASSERT_THAT(QuxDecl, NotNull()); 1491 1492 ASSERT_TRUE(QuxDecl->getType()->isClassType()); 1493 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1494 1495 FieldDecl *BazDecl = nullptr; 1496 for (FieldDecl *Field : QuxFields) { 1497 if (Field->getNameAsString() == "Baz") { 1498 BazDecl = Field; 1499 } else { 1500 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1501 } 1502 } 1503 ASSERT_THAT(BazDecl, NotNull()); 1504 1505 const auto *QuxLoc = 1506 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1507 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1508 ASSERT_THAT(QuxVal, NotNull()); 1509 1510 const auto *BazLoc = 1511 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1512 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1513 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1514 1515 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1516 ASSERT_THAT(QuuxDecl, NotNull()); 1517 EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal); 1518 }); 1519 } 1520 1521 TEST(TransferTest, UnionThisMember) { 1522 std::string Code = R"( 1523 union A { 1524 int Foo; 1525 int Bar; 1526 1527 void target() { 1528 (void)0; // [[p]] 1529 } 1530 }; 1531 )"; 1532 runDataflow( 1533 Code, 1534 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1535 ASTContext &ASTCtx) { 1536 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1537 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1538 1539 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1540 Env.getThisPointeeStorageLocation()); 1541 ASSERT_THAT(ThisLoc, NotNull()); 1542 1543 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1544 ASSERT_THAT(FooDecl, NotNull()); 1545 1546 const auto *FooLoc = 1547 cast<ScalarStorageLocation>(&ThisLoc->getChild(*FooDecl)); 1548 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 1549 1550 const Value *FooVal = Env.getValue(*FooLoc); 1551 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 1552 1553 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1554 ASSERT_THAT(BarDecl, NotNull()); 1555 1556 const auto *BarLoc = 1557 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1558 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1559 1560 const Value *BarVal = Env.getValue(*BarLoc); 1561 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1562 }); 1563 } 1564 1565 TEST(TransferTest, StructThisInLambda) { 1566 std::string ThisCaptureCode = R"( 1567 struct A { 1568 void frob() { 1569 [this]() { 1570 int Foo = Bar; 1571 // [[p1]] 1572 }(); 1573 } 1574 1575 int Bar; 1576 }; 1577 )"; 1578 runDataflow( 1579 ThisCaptureCode, 1580 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1581 ASTContext &ASTCtx) { 1582 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1")); 1583 const Environment &Env = getEnvironmentAtAnnotation(Results, "p1"); 1584 1585 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1586 Env.getThisPointeeStorageLocation()); 1587 ASSERT_THAT(ThisLoc, NotNull()); 1588 1589 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1590 ASSERT_THAT(BarDecl, NotNull()); 1591 1592 const auto *BarLoc = 1593 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1594 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1595 1596 const Value *BarVal = Env.getValue(*BarLoc); 1597 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1598 1599 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1600 ASSERT_THAT(FooDecl, NotNull()); 1601 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1602 }, 1603 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1604 1605 std::string RefCaptureDefaultCode = R"( 1606 struct A { 1607 void frob() { 1608 [&]() { 1609 int Foo = Bar; 1610 // [[p2]] 1611 }(); 1612 } 1613 1614 int Bar; 1615 }; 1616 )"; 1617 runDataflow( 1618 RefCaptureDefaultCode, 1619 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1620 ASTContext &ASTCtx) { 1621 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2")); 1622 const Environment &Env = getEnvironmentAtAnnotation(Results, "p2"); 1623 1624 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1625 Env.getThisPointeeStorageLocation()); 1626 ASSERT_THAT(ThisLoc, NotNull()); 1627 1628 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1629 ASSERT_THAT(BarDecl, NotNull()); 1630 1631 const auto *BarLoc = 1632 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1633 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1634 1635 const Value *BarVal = Env.getValue(*BarLoc); 1636 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1637 1638 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1639 ASSERT_THAT(FooDecl, NotNull()); 1640 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1641 }, 1642 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1643 1644 std::string FreeFunctionLambdaCode = R"( 1645 void foo() { 1646 int Bar; 1647 [&]() { 1648 int Foo = Bar; 1649 // [[p3]] 1650 }(); 1651 } 1652 )"; 1653 runDataflow( 1654 FreeFunctionLambdaCode, 1655 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1656 ASTContext &ASTCtx) { 1657 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3")); 1658 const Environment &Env = getEnvironmentAtAnnotation(Results, "p3"); 1659 1660 EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull()); 1661 }, 1662 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1663 } 1664 1665 TEST(TransferTest, ConstructorInitializer) { 1666 std::string Code = R"( 1667 struct target { 1668 int Bar; 1669 1670 target(int Foo) : Bar(Foo) { 1671 int Qux = Bar; 1672 // [[p]] 1673 } 1674 }; 1675 )"; 1676 runDataflow( 1677 Code, 1678 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1679 ASTContext &ASTCtx) { 1680 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1681 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1682 1683 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1684 Env.getThisPointeeStorageLocation()); 1685 ASSERT_THAT(ThisLoc, NotNull()); 1686 1687 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1688 ASSERT_THAT(FooDecl, NotNull()); 1689 1690 const auto *FooVal = 1691 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1692 1693 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1694 ASSERT_THAT(QuxDecl, NotNull()); 1695 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1696 }); 1697 } 1698 1699 TEST(TransferTest, DefaultInitializer) { 1700 std::string Code = R"( 1701 struct target { 1702 int Bar; 1703 int Baz = Bar; 1704 1705 target(int Foo) : Bar(Foo) { 1706 int Qux = Baz; 1707 // [[p]] 1708 } 1709 }; 1710 )"; 1711 runDataflow( 1712 Code, 1713 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1714 ASTContext &ASTCtx) { 1715 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1716 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1717 1718 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1719 Env.getThisPointeeStorageLocation()); 1720 ASSERT_THAT(ThisLoc, NotNull()); 1721 1722 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1723 ASSERT_THAT(FooDecl, NotNull()); 1724 1725 const auto *FooVal = 1726 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1727 1728 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1729 ASSERT_THAT(QuxDecl, NotNull()); 1730 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1731 }); 1732 } 1733 1734 TEST(TransferTest, DefaultInitializerReference) { 1735 std::string Code = R"( 1736 struct target { 1737 int &Bar; 1738 int &Baz = Bar; 1739 1740 target(int &Foo) : Bar(Foo) { 1741 int &Qux = Baz; 1742 // [[p]] 1743 } 1744 }; 1745 )"; 1746 runDataflow( 1747 Code, 1748 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1749 ASTContext &ASTCtx) { 1750 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1751 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1752 1753 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1754 Env.getThisPointeeStorageLocation()); 1755 ASSERT_THAT(ThisLoc, NotNull()); 1756 1757 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1758 ASSERT_THAT(FooDecl, NotNull()); 1759 1760 const auto *FooVal = 1761 cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None)); 1762 1763 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1764 ASSERT_THAT(QuxDecl, NotNull()); 1765 1766 const auto *QuxVal = 1767 cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None)); 1768 EXPECT_EQ(&QuxVal->getReferentLoc(), &FooVal->getReferentLoc()); 1769 }); 1770 } 1771 1772 TEST(TransferTest, TemporaryObject) { 1773 std::string Code = R"( 1774 struct A { 1775 int Bar; 1776 }; 1777 1778 void target() { 1779 A Foo = A(); 1780 // [[p]] 1781 } 1782 )"; 1783 runDataflow( 1784 Code, 1785 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1786 ASTContext &ASTCtx) { 1787 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1788 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 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 *FooLoc = cast<AggregateStorageLocation>( 1797 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1798 const auto *BarLoc = 1799 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1800 1801 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1802 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1803 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1804 }); 1805 } 1806 1807 TEST(TransferTest, ElidableConstructor) { 1808 // This test is effectively the same as TransferTest.TemporaryObject, but 1809 // the code is compiled as C++ 14. 1810 std::string Code = R"( 1811 struct A { 1812 int Bar; 1813 }; 1814 1815 void target() { 1816 A Foo = A(); 1817 // [[p]] 1818 } 1819 )"; 1820 runDataflow( 1821 Code, 1822 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1823 ASTContext &ASTCtx) { 1824 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1825 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1826 1827 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1828 ASSERT_THAT(FooDecl, NotNull()); 1829 1830 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1831 ASSERT_THAT(BarDecl, NotNull()); 1832 1833 const auto *FooLoc = cast<AggregateStorageLocation>( 1834 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1835 const auto *BarLoc = 1836 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1837 1838 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1839 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1840 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1841 }, 1842 LangStandard::lang_cxx14); 1843 } 1844 1845 TEST(TransferTest, AssignmentOperator) { 1846 std::string Code = R"( 1847 struct A { 1848 int Baz; 1849 }; 1850 1851 void target() { 1852 A Foo; 1853 A Bar; 1854 // [[p1]] 1855 Foo = Bar; 1856 // [[p2]] 1857 } 1858 )"; 1859 runDataflow( 1860 Code, 1861 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1862 ASTContext &ASTCtx) { 1863 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 1864 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 1865 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 1866 1867 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1868 ASSERT_THAT(FooDecl, NotNull()); 1869 1870 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1871 ASSERT_THAT(BarDecl, NotNull()); 1872 1873 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1874 ASSERT_THAT(BazDecl, NotNull()); 1875 1876 const auto *FooLoc1 = cast<AggregateStorageLocation>( 1877 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 1878 const auto *BarLoc1 = cast<AggregateStorageLocation>( 1879 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 1880 1881 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 1882 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 1883 EXPECT_NE(FooVal1, BarVal1); 1884 1885 const auto *FooBazVal1 = 1886 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 1887 const auto *BarBazVal1 = 1888 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 1889 EXPECT_NE(FooBazVal1, BarBazVal1); 1890 1891 const auto *FooLoc2 = cast<AggregateStorageLocation>( 1892 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 1893 const auto *BarLoc2 = cast<AggregateStorageLocation>( 1894 Env2.getStorageLocation(*BarDecl, SkipPast::None)); 1895 1896 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 1897 const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2)); 1898 EXPECT_EQ(FooVal2, BarVal2); 1899 1900 const auto *FooBazVal2 = 1901 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 1902 const auto *BarBazVal2 = 1903 cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl))); 1904 EXPECT_EQ(FooBazVal2, BarBazVal2); 1905 }); 1906 } 1907 1908 TEST(TransferTest, CopyConstructor) { 1909 std::string Code = R"( 1910 struct A { 1911 int Baz; 1912 }; 1913 1914 void target() { 1915 A Foo; 1916 A Bar = Foo; 1917 // [[p]] 1918 } 1919 )"; 1920 runDataflow( 1921 Code, 1922 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1923 ASTContext &ASTCtx) { 1924 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1925 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1926 1927 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1928 ASSERT_THAT(FooDecl, NotNull()); 1929 1930 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1931 ASSERT_THAT(BarDecl, NotNull()); 1932 1933 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1934 ASSERT_THAT(BazDecl, NotNull()); 1935 1936 const auto *FooLoc = cast<AggregateStorageLocation>( 1937 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1938 const auto *BarLoc = cast<AggregateStorageLocation>( 1939 Env.getStorageLocation(*BarDecl, SkipPast::None)); 1940 1941 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1942 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 1943 EXPECT_EQ(FooVal, BarVal); 1944 1945 const auto *FooBazVal = 1946 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 1947 const auto *BarBazVal = 1948 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 1949 EXPECT_EQ(FooBazVal, BarBazVal); 1950 }); 1951 } 1952 1953 TEST(TransferTest, CopyConstructorWithParens) { 1954 std::string Code = R"( 1955 struct A { 1956 int Baz; 1957 }; 1958 1959 void target() { 1960 A Foo; 1961 A Bar((A(Foo))); 1962 // [[p]] 1963 } 1964 )"; 1965 runDataflow( 1966 Code, 1967 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1968 ASTContext &ASTCtx) { 1969 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1970 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1971 1972 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1973 ASSERT_THAT(FooDecl, NotNull()); 1974 1975 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1976 ASSERT_THAT(BarDecl, NotNull()); 1977 1978 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1979 ASSERT_THAT(BazDecl, NotNull()); 1980 1981 const auto *FooLoc = cast<AggregateStorageLocation>( 1982 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1983 const auto *BarLoc = cast<AggregateStorageLocation>( 1984 Env.getStorageLocation(*BarDecl, SkipPast::None)); 1985 1986 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1987 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 1988 EXPECT_EQ(FooVal, BarVal); 1989 1990 const auto *FooBazVal = 1991 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 1992 const auto *BarBazVal = 1993 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 1994 EXPECT_EQ(FooBazVal, BarBazVal); 1995 }); 1996 } 1997 1998 TEST(TransferTest, MoveConstructor) { 1999 std::string Code = R"( 2000 namespace std { 2001 2002 template <typename T> struct remove_reference { using type = T; }; 2003 template <typename T> struct remove_reference<T&> { using type = T; }; 2004 template <typename T> struct remove_reference<T&&> { using type = T; }; 2005 2006 template <typename T> 2007 using remove_reference_t = typename remove_reference<T>::type; 2008 2009 template <typename T> 2010 std::remove_reference_t<T>&& move(T&& x); 2011 2012 } // namespace std 2013 2014 struct A { 2015 int Baz; 2016 }; 2017 2018 void target() { 2019 A Foo; 2020 A Bar; 2021 // [[p1]] 2022 Foo = std::move(Bar); 2023 // [[p2]] 2024 } 2025 )"; 2026 runDataflow( 2027 Code, 2028 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2029 ASTContext &ASTCtx) { 2030 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 2031 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 2032 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 2033 2034 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2035 ASSERT_THAT(FooDecl, NotNull()); 2036 2037 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2038 ASSERT_THAT(BarDecl, NotNull()); 2039 2040 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2041 ASSERT_THAT(BazDecl, NotNull()); 2042 2043 const auto *FooLoc1 = cast<AggregateStorageLocation>( 2044 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 2045 const auto *BarLoc1 = cast<AggregateStorageLocation>( 2046 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 2047 2048 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 2049 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 2050 EXPECT_NE(FooVal1, BarVal1); 2051 2052 const auto *FooBazVal1 = 2053 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 2054 const auto *BarBazVal1 = 2055 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 2056 EXPECT_NE(FooBazVal1, BarBazVal1); 2057 2058 const auto *FooLoc2 = cast<AggregateStorageLocation>( 2059 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 2060 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 2061 EXPECT_EQ(FooVal2, BarVal1); 2062 2063 const auto *FooBazVal2 = 2064 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 2065 EXPECT_EQ(FooBazVal2, BarBazVal1); 2066 }); 2067 } 2068 2069 TEST(TransferTest, BindTemporary) { 2070 std::string Code = R"( 2071 struct A { 2072 virtual ~A() = default; 2073 2074 int Baz; 2075 }; 2076 2077 void target(A Foo) { 2078 int Bar = A(Foo).Baz; 2079 // [[p]] 2080 } 2081 )"; 2082 runDataflow( 2083 Code, 2084 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2085 ASTContext &ASTCtx) { 2086 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2087 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2088 2089 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2090 ASSERT_THAT(FooDecl, NotNull()); 2091 2092 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2093 ASSERT_THAT(BarDecl, NotNull()); 2094 2095 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2096 ASSERT_THAT(BazDecl, NotNull()); 2097 2098 const auto &FooVal = 2099 *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 2100 const auto *BarVal = 2101 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2102 EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl)); 2103 }); 2104 } 2105 2106 TEST(TransferTest, StaticCast) { 2107 std::string Code = R"( 2108 void target(int Foo) { 2109 int Bar = static_cast<int>(Foo); 2110 // [[p]] 2111 } 2112 )"; 2113 runDataflow( 2114 Code, 2115 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2116 ASTContext &ASTCtx) { 2117 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2118 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2119 2120 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2121 ASSERT_THAT(FooDecl, NotNull()); 2122 2123 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2124 ASSERT_THAT(BarDecl, NotNull()); 2125 2126 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2127 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2128 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2129 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2130 EXPECT_EQ(FooVal, BarVal); 2131 }); 2132 } 2133 2134 TEST(TransferTest, IntegralCast) { 2135 std::string Code = R"( 2136 void target(int Foo) { 2137 long Bar = Foo; 2138 // [[p]] 2139 } 2140 )"; 2141 runDataflow( 2142 Code, 2143 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2144 ASTContext &ASTCtx) { 2145 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2146 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2147 2148 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2149 ASSERT_THAT(FooDecl, NotNull()); 2150 2151 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2152 ASSERT_THAT(BarDecl, NotNull()); 2153 2154 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2155 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2156 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2157 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2158 EXPECT_EQ(FooVal, BarVal); 2159 }); 2160 } 2161 2162 TEST(TransferTest, IntegraltoBooleanCast) { 2163 std::string Code = R"( 2164 void target(int Foo) { 2165 bool Bar = Foo; 2166 // [[p]] 2167 } 2168 )"; 2169 runDataflow( 2170 Code, 2171 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2172 ASTContext &ASTCtx) { 2173 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2174 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2175 2176 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2177 ASSERT_THAT(FooDecl, NotNull()); 2178 2179 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2180 ASSERT_THAT(BarDecl, NotNull()); 2181 2182 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2183 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2184 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2185 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2186 }); 2187 } 2188 2189 TEST(TransferTest, IntegralToBooleanCastFromBool) { 2190 std::string Code = R"( 2191 void target(bool Foo) { 2192 int Zab = Foo; 2193 bool Bar = Zab; 2194 // [[p]] 2195 } 2196 )"; 2197 runDataflow( 2198 Code, 2199 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2200 ASTContext &ASTCtx) { 2201 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2202 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2203 2204 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2205 ASSERT_THAT(FooDecl, NotNull()); 2206 2207 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2208 ASSERT_THAT(BarDecl, NotNull()); 2209 2210 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2211 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2212 EXPECT_TRUE(isa<BoolValue>(FooVal)); 2213 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2214 EXPECT_EQ(FooVal, BarVal); 2215 }); 2216 } 2217 2218 TEST(TransferTest, NullToPointerCast) { 2219 std::string Code = R"( 2220 using my_nullptr_t = decltype(nullptr); 2221 struct Baz {}; 2222 void target() { 2223 int *FooX = nullptr; 2224 int *FooY = nullptr; 2225 bool **Bar = nullptr; 2226 Baz *Baz = nullptr; 2227 my_nullptr_t Null = 0; 2228 // [[p]] 2229 } 2230 )"; 2231 runDataflow( 2232 Code, 2233 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2234 ASTContext &ASTCtx) { 2235 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2236 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2237 2238 const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX"); 2239 ASSERT_THAT(FooXDecl, NotNull()); 2240 2241 const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY"); 2242 ASSERT_THAT(FooYDecl, NotNull()); 2243 2244 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2245 ASSERT_THAT(BarDecl, NotNull()); 2246 2247 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2248 ASSERT_THAT(BazDecl, NotNull()); 2249 2250 const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null"); 2251 ASSERT_THAT(NullDecl, NotNull()); 2252 2253 const auto *FooXVal = 2254 cast<PointerValue>(Env.getValue(*FooXDecl, SkipPast::None)); 2255 const auto *FooYVal = 2256 cast<PointerValue>(Env.getValue(*FooYDecl, SkipPast::None)); 2257 const auto *BarVal = 2258 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2259 const auto *BazVal = 2260 cast<PointerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2261 const auto *NullVal = 2262 cast<PointerValue>(Env.getValue(*NullDecl, SkipPast::None)); 2263 2264 EXPECT_EQ(FooXVal, FooYVal); 2265 EXPECT_NE(FooXVal, BarVal); 2266 EXPECT_NE(FooXVal, BazVal); 2267 EXPECT_NE(BarVal, BazVal); 2268 2269 const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc(); 2270 EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc)); 2271 EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull()); 2272 2273 const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc(); 2274 EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc)); 2275 EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull()); 2276 2277 const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc(); 2278 EXPECT_TRUE(isa<AggregateStorageLocation>(BazPointeeLoc)); 2279 EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull()); 2280 2281 const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc(); 2282 EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc)); 2283 EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull()); 2284 }); 2285 } 2286 2287 TEST(TransferTest, NullToMemberPointerCast) { 2288 std::string Code = R"( 2289 struct Foo {}; 2290 void target(Foo *Foo) { 2291 int Foo::*MemberPointer = nullptr; 2292 // [[p]] 2293 } 2294 )"; 2295 runDataflow( 2296 Code, 2297 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2298 ASTContext &ASTCtx) { 2299 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2300 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2301 2302 const ValueDecl *MemberPointerDecl = 2303 findValueDecl(ASTCtx, "MemberPointer"); 2304 ASSERT_THAT(MemberPointerDecl, NotNull()); 2305 2306 const auto *MemberPointerVal = cast<PointerValue>( 2307 Env.getValue(*MemberPointerDecl, SkipPast::None)); 2308 2309 const StorageLocation &MemberLoc = MemberPointerVal->getPointeeLoc(); 2310 EXPECT_THAT(Env.getValue(MemberLoc), IsNull()); 2311 }); 2312 } 2313 2314 TEST(TransferTest, AddrOfValue) { 2315 std::string Code = R"( 2316 void target() { 2317 int Foo; 2318 int *Bar = &Foo; 2319 // [[p]] 2320 } 2321 )"; 2322 runDataflow( 2323 Code, 2324 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2325 ASTContext &ASTCtx) { 2326 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2327 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2328 2329 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2330 ASSERT_THAT(FooDecl, NotNull()); 2331 2332 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2333 ASSERT_THAT(BarDecl, NotNull()); 2334 2335 const auto *FooLoc = cast<ScalarStorageLocation>( 2336 Env.getStorageLocation(*FooDecl, SkipPast::None)); 2337 const auto *BarVal = 2338 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2339 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc); 2340 }); 2341 } 2342 2343 TEST(TransferTest, AddrOfReference) { 2344 std::string Code = R"( 2345 void target(int *Foo) { 2346 int *Bar = &(*Foo); 2347 // [[p]] 2348 } 2349 )"; 2350 runDataflow( 2351 Code, 2352 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2353 ASTContext &ASTCtx) { 2354 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2355 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2356 2357 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2358 ASSERT_THAT(FooDecl, NotNull()); 2359 2360 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2361 ASSERT_THAT(BarDecl, NotNull()); 2362 2363 const auto *FooVal = 2364 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2365 const auto *BarVal = 2366 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2367 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 2368 }); 2369 } 2370 2371 TEST(TransferTest, DerefDependentPtr) { 2372 std::string Code = R"( 2373 template <typename T> 2374 void target(T *Foo) { 2375 T &Bar = *Foo; 2376 /*[[p]]*/ 2377 } 2378 )"; 2379 runDataflow( 2380 Code, 2381 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2382 ASTContext &ASTCtx) { 2383 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2384 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2385 2386 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2387 ASSERT_THAT(FooDecl, NotNull()); 2388 2389 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2390 ASSERT_THAT(BarDecl, NotNull()); 2391 2392 const auto *FooVal = 2393 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2394 const auto *BarVal = 2395 cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None)); 2396 EXPECT_EQ(&BarVal->getReferentLoc(), &FooVal->getPointeeLoc()); 2397 }); 2398 } 2399 2400 TEST(TransferTest, VarDeclInitAssignConditionalOperator) { 2401 std::string Code = R"( 2402 struct A {}; 2403 2404 void target(A Foo, A Bar, bool Cond) { 2405 A Baz = Cond ? Foo : Bar; 2406 /*[[p]]*/ 2407 } 2408 )"; 2409 runDataflow( 2410 Code, 2411 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2412 ASTContext &ASTCtx) { 2413 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2414 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2415 2416 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2417 ASSERT_THAT(FooDecl, NotNull()); 2418 2419 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2420 ASSERT_THAT(BarDecl, NotNull()); 2421 2422 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2423 ASSERT_THAT(BazDecl, NotNull()); 2424 2425 const auto *FooVal = 2426 cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 2427 const auto *BarVal = 2428 cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None)); 2429 2430 const auto *BazVal = 2431 dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None)); 2432 ASSERT_THAT(BazVal, NotNull()); 2433 2434 EXPECT_NE(BazVal, FooVal); 2435 EXPECT_NE(BazVal, BarVal); 2436 }); 2437 } 2438 2439 TEST(TransferTest, VarDeclInDoWhile) { 2440 std::string Code = R"( 2441 void target(int *Foo) { 2442 do { 2443 int Bar = *Foo; 2444 } while (true); 2445 (void)0; 2446 /*[[p]]*/ 2447 } 2448 )"; 2449 runDataflow( 2450 Code, 2451 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2452 ASTContext &ASTCtx) { 2453 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2454 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2455 2456 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2457 ASSERT_THAT(FooDecl, NotNull()); 2458 2459 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2460 ASSERT_THAT(BarDecl, NotNull()); 2461 2462 const auto *FooVal = 2463 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2464 const auto *FooPointeeVal = 2465 cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc())); 2466 2467 const auto *BarVal = dyn_cast_or_null<IntegerValue>( 2468 Env.getValue(*BarDecl, SkipPast::None)); 2469 ASSERT_THAT(BarVal, NotNull()); 2470 2471 EXPECT_EQ(BarVal, FooPointeeVal); 2472 }); 2473 } 2474 2475 TEST(TransferTest, AggregateInitialization) { 2476 std::string BracesCode = R"( 2477 struct A { 2478 int Foo; 2479 }; 2480 2481 struct B { 2482 int Bar; 2483 A Baz; 2484 int Qux; 2485 }; 2486 2487 void target(int BarArg, int FooArg, int QuxArg) { 2488 B Quux{BarArg, {FooArg}, QuxArg}; 2489 /*[[p]]*/ 2490 } 2491 )"; 2492 std::string BraceEllisionCode = R"( 2493 struct A { 2494 int Foo; 2495 }; 2496 2497 struct B { 2498 int Bar; 2499 A Baz; 2500 int Qux; 2501 }; 2502 2503 void target(int BarArg, int FooArg, int QuxArg) { 2504 B Quux = {BarArg, FooArg, QuxArg}; 2505 /*[[p]]*/ 2506 } 2507 )"; 2508 for (const std::string &Code : {BracesCode, BraceEllisionCode}) { 2509 runDataflow( 2510 Code, 2511 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2512 ASTContext &ASTCtx) { 2513 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2514 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2515 2516 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2517 ASSERT_THAT(FooDecl, NotNull()); 2518 2519 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2520 ASSERT_THAT(BarDecl, NotNull()); 2521 2522 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2523 ASSERT_THAT(BazDecl, NotNull()); 2524 2525 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2526 ASSERT_THAT(QuxDecl, NotNull()); 2527 2528 const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg"); 2529 ASSERT_THAT(FooArgDecl, NotNull()); 2530 2531 const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg"); 2532 ASSERT_THAT(BarArgDecl, NotNull()); 2533 2534 const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg"); 2535 ASSERT_THAT(QuxArgDecl, NotNull()); 2536 2537 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 2538 ASSERT_THAT(QuuxDecl, NotNull()); 2539 2540 const auto *FooArgVal = 2541 cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None)); 2542 const auto *BarArgVal = 2543 cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None)); 2544 const auto *QuxArgVal = 2545 cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None)); 2546 2547 const auto *QuuxVal = 2548 cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None)); 2549 ASSERT_THAT(QuuxVal, NotNull()); 2550 2551 const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl)); 2552 ASSERT_THAT(BazVal, NotNull()); 2553 2554 EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal); 2555 EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal); 2556 EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal); 2557 }); 2558 } 2559 } 2560 2561 TEST(TransferTest, AssignToUnionMember) { 2562 std::string Code = R"( 2563 union A { 2564 int Foo; 2565 }; 2566 2567 void target(int Bar) { 2568 A Baz; 2569 Baz.Foo = Bar; 2570 // [[p]] 2571 } 2572 )"; 2573 runDataflow( 2574 Code, 2575 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2576 ASTContext &ASTCtx) { 2577 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2578 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2579 2580 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2581 ASSERT_THAT(BazDecl, NotNull()); 2582 ASSERT_TRUE(BazDecl->getType()->isUnionType()); 2583 2584 auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields(); 2585 FieldDecl *FooDecl = nullptr; 2586 for (FieldDecl *Field : BazFields) { 2587 if (Field->getNameAsString() == "Foo") { 2588 FooDecl = Field; 2589 } else { 2590 FAIL() << "Unexpected field: " << Field->getNameAsString(); 2591 } 2592 } 2593 ASSERT_THAT(FooDecl, NotNull()); 2594 2595 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>( 2596 Env.getStorageLocation(*BazDecl, SkipPast::None)); 2597 ASSERT_THAT(BazLoc, NotNull()); 2598 ASSERT_THAT(Env.getValue(*BazLoc), NotNull()); 2599 2600 const auto *BazVal = cast<StructValue>(Env.getValue(*BazLoc)); 2601 const auto *FooValFromBazVal = cast<IntegerValue>(BazVal->getChild(*FooDecl)); 2602 const auto *FooValFromBazLoc = cast<IntegerValue>(Env.getValue(BazLoc->getChild(*FooDecl))); 2603 EXPECT_EQ(FooValFromBazLoc, FooValFromBazVal); 2604 2605 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2606 ASSERT_THAT(BarDecl, NotNull()); 2607 const auto *BarLoc = Env.getStorageLocation(*BarDecl, SkipPast::None); 2608 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 2609 2610 EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazVal); 2611 EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazLoc); 2612 }); 2613 } 2614 2615 TEST(TransferTest, AssignFromBoolLiteral) { 2616 std::string Code = R"( 2617 void target() { 2618 bool Foo = true; 2619 bool Bar = false; 2620 // [[p]] 2621 } 2622 )"; 2623 runDataflow( 2624 Code, 2625 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2626 ASTContext &ASTCtx) { 2627 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2628 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2629 2630 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2631 ASSERT_THAT(FooDecl, NotNull()); 2632 2633 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2634 Env.getValue(*FooDecl, SkipPast::None)); 2635 ASSERT_THAT(FooVal, NotNull()); 2636 2637 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2638 ASSERT_THAT(BarDecl, NotNull()); 2639 2640 const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>( 2641 Env.getValue(*BarDecl, SkipPast::None)); 2642 ASSERT_THAT(BarVal, NotNull()); 2643 2644 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true)); 2645 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false)); 2646 }); 2647 } 2648 2649 TEST(TransferTest, AssignFromCompositeBoolExpression) { 2650 { 2651 std::string Code = R"( 2652 void target(bool Foo, bool Bar, bool Qux) { 2653 bool Baz = (Foo) && (Bar || Qux); 2654 // [[p]] 2655 } 2656 )"; 2657 runDataflow( 2658 Code, 2659 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2660 ASTContext &ASTCtx) { 2661 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2662 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2663 2664 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2665 ASSERT_THAT(FooDecl, NotNull()); 2666 2667 const auto *FooVal = dyn_cast_or_null<BoolValue>( 2668 Env.getValue(*FooDecl, SkipPast::None)); 2669 ASSERT_THAT(FooVal, NotNull()); 2670 2671 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2672 ASSERT_THAT(BarDecl, NotNull()); 2673 2674 const auto *BarVal = dyn_cast_or_null<BoolValue>( 2675 Env.getValue(*BarDecl, SkipPast::None)); 2676 ASSERT_THAT(BarVal, NotNull()); 2677 2678 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2679 ASSERT_THAT(QuxDecl, NotNull()); 2680 2681 const auto *QuxVal = dyn_cast_or_null<BoolValue>( 2682 Env.getValue(*QuxDecl, SkipPast::None)); 2683 ASSERT_THAT(QuxVal, NotNull()); 2684 2685 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2686 ASSERT_THAT(BazDecl, NotNull()); 2687 2688 const auto *BazVal = dyn_cast_or_null<ConjunctionValue>( 2689 Env.getValue(*BazDecl, SkipPast::None)); 2690 ASSERT_THAT(BazVal, NotNull()); 2691 EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal); 2692 2693 const auto *BazRightSubValVal = 2694 cast<DisjunctionValue>(&BazVal->getRightSubValue()); 2695 EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal); 2696 EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal); 2697 }); 2698 } 2699 2700 { 2701 std::string Code = R"( 2702 void target(bool Foo, bool Bar, bool Qux) { 2703 bool Baz = (Foo && Qux) || (Bar); 2704 // [[p]] 2705 } 2706 )"; 2707 runDataflow( 2708 Code, 2709 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2710 ASTContext &ASTCtx) { 2711 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2712 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2713 2714 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2715 ASSERT_THAT(FooDecl, NotNull()); 2716 2717 const auto *FooVal = dyn_cast_or_null<BoolValue>( 2718 Env.getValue(*FooDecl, SkipPast::None)); 2719 ASSERT_THAT(FooVal, NotNull()); 2720 2721 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2722 ASSERT_THAT(BarDecl, NotNull()); 2723 2724 const auto *BarVal = dyn_cast_or_null<BoolValue>( 2725 Env.getValue(*BarDecl, SkipPast::None)); 2726 ASSERT_THAT(BarVal, NotNull()); 2727 2728 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2729 ASSERT_THAT(QuxDecl, NotNull()); 2730 2731 const auto *QuxVal = dyn_cast_or_null<BoolValue>( 2732 Env.getValue(*QuxDecl, SkipPast::None)); 2733 ASSERT_THAT(QuxVal, NotNull()); 2734 2735 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2736 ASSERT_THAT(BazDecl, NotNull()); 2737 2738 const auto *BazVal = dyn_cast_or_null<DisjunctionValue>( 2739 Env.getValue(*BazDecl, SkipPast::None)); 2740 ASSERT_THAT(BazVal, NotNull()); 2741 2742 const auto *BazLeftSubValVal = 2743 cast<ConjunctionValue>(&BazVal->getLeftSubValue()); 2744 EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal); 2745 EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal); 2746 2747 EXPECT_EQ(&BazVal->getRightSubValue(), BarVal); 2748 }); 2749 } 2750 2751 { 2752 std::string Code = R"( 2753 void target(bool A, bool B, bool C, bool D) { 2754 bool Foo = ((A && B) && C) && D; 2755 // [[p]] 2756 } 2757 )"; 2758 runDataflow( 2759 Code, 2760 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2761 ASTContext &ASTCtx) { 2762 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2763 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2764 2765 const ValueDecl *ADecl = findValueDecl(ASTCtx, "A"); 2766 ASSERT_THAT(ADecl, NotNull()); 2767 2768 const auto *AVal = 2769 dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl, SkipPast::None)); 2770 ASSERT_THAT(AVal, NotNull()); 2771 2772 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 2773 ASSERT_THAT(BDecl, NotNull()); 2774 2775 const auto *BVal = 2776 dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl, SkipPast::None)); 2777 ASSERT_THAT(BVal, NotNull()); 2778 2779 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 2780 ASSERT_THAT(CDecl, NotNull()); 2781 2782 const auto *CVal = 2783 dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 2784 ASSERT_THAT(CVal, NotNull()); 2785 2786 const ValueDecl *DDecl = findValueDecl(ASTCtx, "D"); 2787 ASSERT_THAT(DDecl, NotNull()); 2788 2789 const auto *DVal = 2790 dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl, SkipPast::None)); 2791 ASSERT_THAT(DVal, NotNull()); 2792 2793 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2794 ASSERT_THAT(FooDecl, NotNull()); 2795 2796 const auto *FooVal = dyn_cast_or_null<ConjunctionValue>( 2797 Env.getValue(*FooDecl, SkipPast::None)); 2798 ASSERT_THAT(FooVal, NotNull()); 2799 2800 const auto &FooLeftSubVal = 2801 cast<ConjunctionValue>(FooVal->getLeftSubValue()); 2802 const auto &FooLeftLeftSubVal = 2803 cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue()); 2804 EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal); 2805 EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal); 2806 EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal); 2807 EXPECT_EQ(&FooVal->getRightSubValue(), DVal); 2808 }); 2809 } 2810 } 2811 2812 TEST(TransferTest, AssignFromBoolNegation) { 2813 std::string Code = R"( 2814 void target() { 2815 bool Foo = true; 2816 bool Bar = !(Foo); 2817 // [[p]] 2818 } 2819 )"; 2820 runDataflow( 2821 Code, 2822 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2823 ASTContext &ASTCtx) { 2824 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2825 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2826 2827 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2828 ASSERT_THAT(FooDecl, NotNull()); 2829 2830 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2831 Env.getValue(*FooDecl, SkipPast::None)); 2832 ASSERT_THAT(FooVal, NotNull()); 2833 2834 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2835 ASSERT_THAT(BarDecl, NotNull()); 2836 2837 const auto *BarVal = dyn_cast_or_null<NegationValue>( 2838 Env.getValue(*BarDecl, SkipPast::None)); 2839 ASSERT_THAT(BarVal, NotNull()); 2840 2841 EXPECT_EQ(&BarVal->getSubVal(), FooVal); 2842 }); 2843 } 2844 2845 TEST(TransferTest, BuiltinExpect) { 2846 std::string Code = R"( 2847 void target(long Foo) { 2848 long Bar = __builtin_expect(Foo, true); 2849 /*[[p]]*/ 2850 } 2851 )"; 2852 runDataflow( 2853 Code, 2854 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2855 ASTContext &ASTCtx) { 2856 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2857 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2858 2859 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2860 ASSERT_THAT(FooDecl, NotNull()); 2861 2862 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2863 ASSERT_THAT(BarDecl, NotNull()); 2864 2865 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2866 Env.getValue(*BarDecl, SkipPast::None)); 2867 }); 2868 } 2869 2870 // `__builtin_expect` takes and returns a `long` argument, so other types 2871 // involve casts. This verifies that we identify the input and output in that 2872 // case. 2873 TEST(TransferTest, BuiltinExpectBoolArg) { 2874 std::string Code = R"( 2875 void target(bool Foo) { 2876 bool Bar = __builtin_expect(Foo, true); 2877 /*[[p]]*/ 2878 } 2879 )"; 2880 runDataflow( 2881 Code, 2882 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2883 ASTContext &ASTCtx) { 2884 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2885 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2886 2887 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2888 ASSERT_THAT(FooDecl, NotNull()); 2889 2890 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2891 ASSERT_THAT(BarDecl, NotNull()); 2892 2893 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2894 Env.getValue(*BarDecl, SkipPast::None)); 2895 }); 2896 } 2897 2898 TEST(TransferTest, BuiltinUnreachable) { 2899 std::string Code = R"( 2900 void target(bool Foo) { 2901 bool Bar = false; 2902 if (Foo) 2903 Bar = Foo; 2904 else 2905 __builtin_unreachable(); 2906 (void)0; 2907 /*[[p]]*/ 2908 } 2909 )"; 2910 runDataflow( 2911 Code, 2912 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2913 ASTContext &ASTCtx) { 2914 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2915 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2916 2917 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2918 ASSERT_THAT(FooDecl, NotNull()); 2919 2920 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2921 ASSERT_THAT(BarDecl, NotNull()); 2922 2923 // `__builtin_unreachable` promises that the code is 2924 // unreachable, so the compiler treats the "then" branch as the 2925 // only possible predecessor of this statement. 2926 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2927 Env.getValue(*BarDecl, SkipPast::None)); 2928 }); 2929 } 2930 2931 TEST(TransferTest, BuiltinTrap) { 2932 std::string Code = R"( 2933 void target(bool Foo) { 2934 bool Bar = false; 2935 if (Foo) 2936 Bar = Foo; 2937 else 2938 __builtin_trap(); 2939 (void)0; 2940 /*[[p]]*/ 2941 } 2942 )"; 2943 runDataflow( 2944 Code, 2945 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2946 ASTContext &ASTCtx) { 2947 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2948 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2949 2950 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2951 ASSERT_THAT(FooDecl, NotNull()); 2952 2953 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2954 ASSERT_THAT(BarDecl, NotNull()); 2955 2956 // `__builtin_trap` ensures program termination, so only the 2957 // "then" branch is a predecessor of this statement. 2958 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2959 Env.getValue(*BarDecl, SkipPast::None)); 2960 }); 2961 } 2962 2963 TEST(TransferTest, BuiltinDebugTrap) { 2964 std::string Code = R"( 2965 void target(bool Foo) { 2966 bool Bar = false; 2967 if (Foo) 2968 Bar = Foo; 2969 else 2970 __builtin_debugtrap(); 2971 (void)0; 2972 /*[[p]]*/ 2973 } 2974 )"; 2975 runDataflow( 2976 Code, 2977 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2978 ASTContext &ASTCtx) { 2979 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2980 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2981 2982 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2983 ASSERT_THAT(FooDecl, NotNull()); 2984 2985 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2986 ASSERT_THAT(BarDecl, NotNull()); 2987 2988 // `__builtin_debugtrap` doesn't ensure program termination. 2989 EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None), 2990 Env.getValue(*BarDecl, SkipPast::None)); 2991 }); 2992 } 2993 2994 TEST(TransferTest, StaticIntSingleVarDecl) { 2995 std::string Code = R"( 2996 void target() { 2997 static int Foo; 2998 // [[p]] 2999 } 3000 )"; 3001 runDataflow( 3002 Code, 3003 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3004 ASTContext &ASTCtx) { 3005 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3006 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3007 3008 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3009 ASSERT_THAT(FooDecl, NotNull()); 3010 3011 const StorageLocation *FooLoc = 3012 Env.getStorageLocation(*FooDecl, SkipPast::None); 3013 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3014 3015 const Value *FooVal = Env.getValue(*FooLoc); 3016 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3017 }); 3018 } 3019 3020 TEST(TransferTest, StaticIntGroupVarDecl) { 3021 std::string Code = R"( 3022 void target() { 3023 static int Foo, Bar; 3024 (void)0; 3025 // [[p]] 3026 } 3027 )"; 3028 runDataflow( 3029 Code, 3030 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3031 ASTContext &ASTCtx) { 3032 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3033 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3034 3035 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3036 ASSERT_THAT(FooDecl, NotNull()); 3037 3038 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3039 ASSERT_THAT(BarDecl, NotNull()); 3040 3041 const StorageLocation *FooLoc = 3042 Env.getStorageLocation(*FooDecl, SkipPast::None); 3043 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3044 3045 const StorageLocation *BarLoc = 3046 Env.getStorageLocation(*BarDecl, SkipPast::None); 3047 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 3048 3049 const Value *FooVal = Env.getValue(*FooLoc); 3050 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3051 3052 const Value *BarVal = Env.getValue(*BarLoc); 3053 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 3054 3055 EXPECT_NE(FooVal, BarVal); 3056 }); 3057 } 3058 3059 TEST(TransferTest, GlobalIntVarDecl) { 3060 std::string Code = R"( 3061 static int Foo; 3062 3063 void target() { 3064 int Bar = Foo; 3065 int Baz = Foo; 3066 // [[p]] 3067 } 3068 )"; 3069 runDataflow( 3070 Code, 3071 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3072 ASTContext &ASTCtx) { 3073 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3074 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3075 3076 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3077 ASSERT_THAT(BarDecl, NotNull()); 3078 3079 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3080 ASSERT_THAT(BazDecl, NotNull()); 3081 3082 const Value *BarVal = 3083 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3084 const Value *BazVal = 3085 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 3086 EXPECT_EQ(BarVal, BazVal); 3087 }); 3088 } 3089 3090 TEST(TransferTest, StaticMemberIntVarDecl) { 3091 std::string Code = R"( 3092 struct A { 3093 static int Foo; 3094 }; 3095 3096 void target(A a) { 3097 int Bar = a.Foo; 3098 int Baz = a.Foo; 3099 // [[p]] 3100 } 3101 )"; 3102 runDataflow( 3103 Code, 3104 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3105 ASTContext &ASTCtx) { 3106 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3107 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3108 3109 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3110 ASSERT_THAT(BarDecl, NotNull()); 3111 3112 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3113 ASSERT_THAT(BazDecl, NotNull()); 3114 3115 const Value *BarVal = 3116 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3117 const Value *BazVal = 3118 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 3119 EXPECT_EQ(BarVal, BazVal); 3120 }); 3121 } 3122 3123 TEST(TransferTest, StaticMemberRefVarDecl) { 3124 std::string Code = R"( 3125 struct A { 3126 static int &Foo; 3127 }; 3128 3129 void target(A a) { 3130 int Bar = a.Foo; 3131 int Baz = a.Foo; 3132 // [[p]] 3133 } 3134 )"; 3135 runDataflow( 3136 Code, 3137 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3138 ASTContext &ASTCtx) { 3139 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3140 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3141 3142 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3143 ASSERT_THAT(BarDecl, NotNull()); 3144 3145 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3146 ASSERT_THAT(BazDecl, NotNull()); 3147 3148 const Value *BarVal = 3149 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3150 const Value *BazVal = 3151 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 3152 EXPECT_EQ(BarVal, BazVal); 3153 }); 3154 } 3155 3156 TEST(TransferTest, AssignMemberBeforeCopy) { 3157 std::string Code = R"( 3158 struct A { 3159 int Foo; 3160 }; 3161 3162 void target() { 3163 A A1; 3164 A A2; 3165 int Bar; 3166 A1.Foo = Bar; 3167 A2 = A1; 3168 // [[p]] 3169 } 3170 )"; 3171 runDataflow( 3172 Code, 3173 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3174 ASTContext &ASTCtx) { 3175 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3176 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3177 3178 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3179 ASSERT_THAT(FooDecl, NotNull()); 3180 3181 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3182 ASSERT_THAT(BarDecl, NotNull()); 3183 3184 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); 3185 ASSERT_THAT(A1Decl, NotNull()); 3186 3187 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); 3188 ASSERT_THAT(A2Decl, NotNull()); 3189 3190 const auto *BarVal = 3191 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3192 3193 const auto *A2Val = 3194 cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None)); 3195 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal); 3196 }); 3197 } 3198 3199 TEST(TransferTest, BooleanEquality) { 3200 std::string Code = R"( 3201 void target(bool Bar) { 3202 bool Foo = true; 3203 if (Bar == Foo) { 3204 (void)0; 3205 /*[[p-then]]*/ 3206 } else { 3207 (void)0; 3208 /*[[p-else]]*/ 3209 } 3210 } 3211 )"; 3212 runDataflow( 3213 Code, 3214 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3215 ASTContext &ASTCtx) { 3216 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else")); 3217 const Environment &EnvThen = 3218 getEnvironmentAtAnnotation(Results, "p-then"); 3219 const Environment &EnvElse = 3220 getEnvironmentAtAnnotation(Results, "p-else"); 3221 3222 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3223 ASSERT_THAT(BarDecl, NotNull()); 3224 3225 auto &BarValThen = 3226 *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None)); 3227 EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen)); 3228 3229 auto &BarValElse = 3230 *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None)); 3231 EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse)); 3232 }); 3233 } 3234 3235 TEST(TransferTest, BooleanInequality) { 3236 std::string Code = R"( 3237 void target(bool Bar) { 3238 bool Foo = true; 3239 if (Bar != Foo) { 3240 (void)0; 3241 /*[[p-then]]*/ 3242 } else { 3243 (void)0; 3244 /*[[p-else]]*/ 3245 } 3246 } 3247 )"; 3248 runDataflow( 3249 Code, 3250 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3251 ASTContext &ASTCtx) { 3252 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else")); 3253 const Environment &EnvThen = 3254 getEnvironmentAtAnnotation(Results, "p-then"); 3255 const Environment &EnvElse = 3256 getEnvironmentAtAnnotation(Results, "p-else"); 3257 3258 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3259 ASSERT_THAT(BarDecl, NotNull()); 3260 3261 auto &BarValThen = 3262 *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None)); 3263 EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen)); 3264 3265 auto &BarValElse = 3266 *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None)); 3267 EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse)); 3268 }); 3269 } 3270 3271 TEST(TransferTest, CorrelatedBranches) { 3272 std::string Code = R"( 3273 void target(bool B, bool C) { 3274 if (B) { 3275 return; 3276 } 3277 (void)0; 3278 /*[[p0]]*/ 3279 if (C) { 3280 B = true; 3281 /*[[p1]]*/ 3282 } 3283 if (B) { 3284 (void)0; 3285 /*[[p2]]*/ 3286 } 3287 } 3288 )"; 3289 runDataflow( 3290 Code, 3291 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3292 ASTContext &ASTCtx) { 3293 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2")); 3294 3295 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3296 ASSERT_THAT(CDecl, NotNull()); 3297 3298 { 3299 const Environment &Env = getEnvironmentAtAnnotation(Results, "p0"); 3300 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3301 ASSERT_THAT(BDecl, NotNull()); 3302 auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None)); 3303 3304 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal))); 3305 } 3306 3307 { 3308 const Environment &Env = getEnvironmentAtAnnotation(Results, "p1"); 3309 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 3310 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3311 } 3312 3313 { 3314 const Environment &Env = getEnvironmentAtAnnotation(Results, "p2"); 3315 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 3316 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3317 } 3318 }); 3319 } 3320 3321 TEST(TransferTest, LoopWithAssignmentConverges) { 3322 std::string Code = R"( 3323 bool foo(); 3324 3325 void target() { 3326 do { 3327 bool Bar = foo(); 3328 if (Bar) break; 3329 (void)Bar; 3330 /*[[p]]*/ 3331 } while (true); 3332 } 3333 )"; 3334 // The key property that we are verifying is implicit in `runDataflow` -- 3335 // namely, that the analysis succeeds, rather than hitting the maximum number 3336 // of iterations. 3337 runDataflow( 3338 Code, 3339 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3340 ASTContext &ASTCtx) { 3341 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3342 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3343 3344 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3345 ASSERT_THAT(BarDecl, NotNull()); 3346 3347 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 3348 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3349 }); 3350 } 3351 3352 TEST(TransferTest, LoopWithStagedAssignments) { 3353 std::string Code = R"( 3354 bool foo(); 3355 3356 void target() { 3357 bool Bar = false; 3358 bool Err = false; 3359 while (foo()) { 3360 if (Bar) 3361 Err = true; 3362 Bar = true; 3363 /*[[p]]*/ 3364 } 3365 } 3366 )"; 3367 runDataflow( 3368 Code, 3369 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3370 ASTContext &ASTCtx) { 3371 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3372 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3373 3374 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3375 ASSERT_THAT(BarDecl, NotNull()); 3376 const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err"); 3377 ASSERT_THAT(ErrDecl, NotNull()); 3378 3379 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 3380 auto &ErrVal = *cast<BoolValue>(Env.getValue(*ErrDecl, SkipPast::None)); 3381 EXPECT_TRUE(Env.flowConditionImplies(BarVal)); 3382 // An unsound analysis, for example only evaluating the loop once, can 3383 // conclude that `Err` is false. So, we test that this conclusion is not 3384 // reached. 3385 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(ErrVal))); 3386 }); 3387 } 3388 3389 TEST(TransferTest, LoopWithReferenceAssignmentConverges) { 3390 std::string Code = R"( 3391 bool &foo(); 3392 3393 void target() { 3394 do { 3395 bool& Bar = foo(); 3396 if (Bar) break; 3397 (void)Bar; 3398 /*[[p]]*/ 3399 } while (true); 3400 } 3401 )"; 3402 // The key property that we are verifying is that the analysis succeeds, 3403 // rather than hitting the maximum number of iterations. 3404 runDataflow( 3405 Code, 3406 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3407 ASTContext &ASTCtx) { 3408 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3409 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3410 3411 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3412 ASSERT_THAT(BarDecl, NotNull()); 3413 3414 auto &BarVal = 3415 *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference)); 3416 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3417 }); 3418 } 3419 3420 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) { 3421 std::string Code = R"( 3422 struct Lookup { 3423 int x; 3424 }; 3425 3426 void target(Lookup val, bool b) { 3427 const Lookup* l = nullptr; 3428 while (b) { 3429 l = &val; 3430 /*[[p-inner]]*/ 3431 } 3432 (void)0; 3433 /*[[p-outer]]*/ 3434 } 3435 )"; 3436 // The key property that we are verifying is implicit in `runDataflow` -- 3437 // namely, that the analysis succeeds, rather than hitting the maximum number 3438 // of iterations. 3439 runDataflow( 3440 Code, 3441 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3442 ASTContext &ASTCtx) { 3443 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer")); 3444 const Environment &InnerEnv = 3445 getEnvironmentAtAnnotation(Results, "p-inner"); 3446 const Environment &OuterEnv = 3447 getEnvironmentAtAnnotation(Results, "p-outer"); 3448 3449 const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val"); 3450 ASSERT_THAT(ValDecl, NotNull()); 3451 3452 const ValueDecl *LDecl = findValueDecl(ASTCtx, "l"); 3453 ASSERT_THAT(LDecl, NotNull()); 3454 3455 // Inner. 3456 auto *LVal = 3457 dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl, SkipPast::None)); 3458 ASSERT_THAT(LVal, NotNull()); 3459 3460 EXPECT_EQ(&LVal->getPointeeLoc(), 3461 InnerEnv.getStorageLocation(*ValDecl, SkipPast::Reference)); 3462 3463 // Outer. 3464 LVal = 3465 dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl, SkipPast::None)); 3466 ASSERT_THAT(LVal, NotNull()); 3467 3468 // The loop body may not have been executed, so we should not conclude 3469 // that `l` points to `val`. 3470 EXPECT_NE(&LVal->getPointeeLoc(), 3471 OuterEnv.getStorageLocation(*ValDecl, SkipPast::Reference)); 3472 }); 3473 } 3474 3475 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { 3476 std::string Code = R"( 3477 union Union { 3478 int A; 3479 float B; 3480 }; 3481 3482 void foo() { 3483 Union A; 3484 Union B; 3485 A = B; 3486 } 3487 )"; 3488 // This is a crash regression test when calling the transfer function on a 3489 // `CXXThisExpr` that refers to a union. 3490 runDataflow( 3491 Code, 3492 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &, 3493 ASTContext &) {}, 3494 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator="); 3495 } 3496 3497 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) { 3498 std::string Code = R"( 3499 struct A { 3500 int Foo; 3501 int Bar; 3502 }; 3503 3504 void target() { 3505 int Qux; 3506 A Baz; 3507 Baz.Foo = Qux; 3508 auto &FooRef = Baz.Foo; 3509 auto &BarRef = Baz.Bar; 3510 auto &[BoundFooRef, BoundBarRef] = Baz; 3511 // [[p]] 3512 } 3513 )"; 3514 runDataflow( 3515 Code, 3516 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3517 ASTContext &ASTCtx) { 3518 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3519 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3520 3521 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3522 ASSERT_THAT(FooRefDecl, NotNull()); 3523 3524 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3525 ASSERT_THAT(BarRefDecl, NotNull()); 3526 3527 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3528 ASSERT_THAT(QuxDecl, NotNull()); 3529 3530 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3531 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3532 3533 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3534 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3535 3536 const StorageLocation *FooRefLoc = 3537 Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); 3538 ASSERT_THAT(FooRefLoc, NotNull()); 3539 3540 const StorageLocation *BarRefLoc = 3541 Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); 3542 ASSERT_THAT(BarRefLoc, NotNull()); 3543 3544 const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); 3545 ASSERT_THAT(QuxVal, NotNull()); 3546 3547 const StorageLocation *BoundFooRefLoc = 3548 Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference); 3549 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3550 3551 const StorageLocation *BoundBarRefLoc = 3552 Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference); 3553 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3554 3555 EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal); 3556 }); 3557 } 3558 3559 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) { 3560 std::string Code = R"( 3561 struct A { 3562 int &Foo; 3563 int &Bar; 3564 }; 3565 3566 void target(A Baz) { 3567 int Qux; 3568 Baz.Foo = Qux; 3569 auto &FooRef = Baz.Foo; 3570 auto &BarRef = Baz.Bar; 3571 auto &[BoundFooRef, BoundBarRef] = Baz; 3572 // [[p]] 3573 } 3574 )"; 3575 runDataflow( 3576 Code, 3577 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3578 ASTContext &ASTCtx) { 3579 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3580 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3581 3582 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3583 ASSERT_THAT(FooRefDecl, NotNull()); 3584 3585 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3586 ASSERT_THAT(BarRefDecl, NotNull()); 3587 3588 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3589 ASSERT_THAT(QuxDecl, NotNull()); 3590 3591 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3592 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3593 3594 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3595 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3596 3597 const StorageLocation *FooRefLoc = 3598 Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); 3599 ASSERT_THAT(FooRefLoc, NotNull()); 3600 3601 const StorageLocation *BarRefLoc = 3602 Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); 3603 ASSERT_THAT(BarRefLoc, NotNull()); 3604 3605 const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); 3606 ASSERT_THAT(QuxVal, NotNull()); 3607 3608 const StorageLocation *BoundFooRefLoc = 3609 Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference); 3610 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3611 3612 const StorageLocation *BoundBarRefLoc = 3613 Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference); 3614 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3615 3616 EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal); 3617 }); 3618 } 3619 3620 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) { 3621 std::string Code = R"( 3622 struct A { 3623 int Foo; 3624 int Bar; 3625 }; 3626 3627 void target() { 3628 int Qux; 3629 A Baz; 3630 Baz.Foo = Qux; 3631 auto &FooRef = Baz.Foo; 3632 auto &BarRef = Baz.Bar; 3633 auto [BoundFoo, BoundBar] = Baz; 3634 // [[p]] 3635 } 3636 )"; 3637 runDataflow( 3638 Code, 3639 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3640 ASTContext &ASTCtx) { 3641 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3642 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3643 3644 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3645 ASSERT_THAT(FooRefDecl, NotNull()); 3646 3647 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3648 ASSERT_THAT(BarRefDecl, NotNull()); 3649 3650 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 3651 ASSERT_THAT(BoundFooDecl, NotNull()); 3652 3653 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 3654 ASSERT_THAT(BoundBarDecl, NotNull()); 3655 3656 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3657 ASSERT_THAT(QuxDecl, NotNull()); 3658 3659 const StorageLocation *FooRefLoc = 3660 Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); 3661 ASSERT_THAT(FooRefLoc, NotNull()); 3662 3663 const StorageLocation *BarRefLoc = 3664 Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); 3665 ASSERT_THAT(BarRefLoc, NotNull()); 3666 3667 const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); 3668 ASSERT_THAT(QuxVal, NotNull()); 3669 3670 const StorageLocation *BoundFooLoc = 3671 Env.getStorageLocation(*BoundFooDecl, SkipPast::Reference); 3672 EXPECT_NE(BoundFooLoc, FooRefLoc); 3673 3674 const StorageLocation *BoundBarLoc = 3675 Env.getStorageLocation(*BoundBarDecl, SkipPast::Reference); 3676 EXPECT_NE(BoundBarLoc, BarRefLoc); 3677 3678 EXPECT_EQ(Env.getValue(*BoundFooDecl, SkipPast::Reference), QuxVal); 3679 }); 3680 } 3681 3682 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) { 3683 std::string Code = R"( 3684 namespace std { 3685 using size_t = int; 3686 template <class> struct tuple_size; 3687 template <std::size_t, class> struct tuple_element; 3688 template <class...> class tuple; 3689 3690 namespace { 3691 template <class T, T v> 3692 struct size_helper { static const T value = v; }; 3693 } // namespace 3694 3695 template <class... T> 3696 struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {}; 3697 3698 template <std::size_t I, class... T> 3699 struct tuple_element<I, tuple<T...>> { 3700 using type = __type_pack_element<I, T...>; 3701 }; 3702 3703 template <class...> class tuple {}; 3704 3705 template <std::size_t I, class... T> 3706 typename tuple_element<I, tuple<T...>>::type get(tuple<T...>); 3707 } // namespace std 3708 3709 std::tuple<bool, int> makeTuple(); 3710 3711 void target(bool B) { 3712 auto [BoundFoo, BoundBar] = makeTuple(); 3713 bool Baz; 3714 // Include if-then-else to test interaction of `BindingDecl` with join. 3715 if (B) { 3716 Baz = BoundFoo; 3717 (void)BoundBar; 3718 // [[p1]] 3719 } else { 3720 Baz = BoundFoo; 3721 } 3722 (void)0; 3723 // [[p2]] 3724 } 3725 )"; 3726 runDataflow( 3727 Code, 3728 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3729 ASTContext &ASTCtx) { 3730 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 3731 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 3732 3733 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 3734 ASSERT_THAT(BoundFooDecl, NotNull()); 3735 3736 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 3737 ASSERT_THAT(BoundBarDecl, NotNull()); 3738 3739 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3740 ASSERT_THAT(BazDecl, NotNull()); 3741 3742 const Value *BoundFooValue = 3743 Env1.getValue(*BoundFooDecl, SkipPast::Reference); 3744 ASSERT_THAT(BoundFooValue, NotNull()); 3745 EXPECT_TRUE(isa<BoolValue>(BoundFooValue)); 3746 3747 const Value *BoundBarValue = 3748 Env1.getValue(*BoundBarDecl, SkipPast::Reference); 3749 ASSERT_THAT(BoundBarValue, NotNull()); 3750 EXPECT_TRUE(isa<IntegerValue>(BoundBarValue)); 3751 3752 // Test that a `DeclRefExpr` to a `BindingDecl` works as expected. 3753 EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), BoundFooValue); 3754 3755 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 3756 3757 // Test that `BoundFooDecl` retains the value we expect, after the join. 3758 BoundFooValue = Env2.getValue(*BoundFooDecl, SkipPast::Reference); 3759 EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BoundFooValue); 3760 }); 3761 } 3762 3763 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) { 3764 std::string Code = R"( 3765 namespace std { 3766 using size_t = int; 3767 template <class> struct tuple_size; 3768 template <std::size_t, class> struct tuple_element; 3769 template <class...> class tuple; 3770 3771 namespace { 3772 template <class T, T v> 3773 struct size_helper { static const T value = v; }; 3774 } // namespace 3775 3776 template <class... T> 3777 struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {}; 3778 3779 template <std::size_t I, class... T> 3780 struct tuple_element<I, tuple<T...>> { 3781 using type = __type_pack_element<I, T...>; 3782 }; 3783 3784 template <class...> class tuple {}; 3785 3786 template <std::size_t I, class... T> 3787 typename tuple_element<I, tuple<T...>>::type get(tuple<T...>); 3788 } // namespace std 3789 3790 std::tuple<bool, int> &getTuple(); 3791 3792 void target(bool B) { 3793 auto &[BoundFoo, BoundBar] = getTuple(); 3794 bool Baz; 3795 // Include if-then-else to test interaction of `BindingDecl` with join. 3796 if (B) { 3797 Baz = BoundFoo; 3798 (void)BoundBar; 3799 // [[p1]] 3800 } else { 3801 Baz = BoundFoo; 3802 } 3803 (void)0; 3804 // [[p2]] 3805 } 3806 )"; 3807 runDataflow( 3808 Code, 3809 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3810 ASTContext &ASTCtx) { 3811 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 3812 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 3813 3814 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 3815 ASSERT_THAT(BoundFooDecl, NotNull()); 3816 3817 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 3818 ASSERT_THAT(BoundBarDecl, NotNull()); 3819 3820 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3821 ASSERT_THAT(BazDecl, NotNull()); 3822 3823 const Value *BoundFooValue = 3824 Env1.getValue(*BoundFooDecl, SkipPast::Reference); 3825 ASSERT_THAT(BoundFooValue, NotNull()); 3826 EXPECT_TRUE(isa<BoolValue>(BoundFooValue)); 3827 3828 const Value *BoundBarValue = 3829 Env1.getValue(*BoundBarDecl, SkipPast::Reference); 3830 ASSERT_THAT(BoundBarValue, NotNull()); 3831 EXPECT_TRUE(isa<IntegerValue>(BoundBarValue)); 3832 3833 // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type) 3834 // works as expected. We don't test aliasing properties of the 3835 // reference, because we don't model `std::get` and so have no way to 3836 // equate separate references into the tuple. 3837 EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), BoundFooValue); 3838 3839 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 3840 3841 // Test that `BoundFooDecl` retains the value we expect, after the join. 3842 BoundFooValue = Env2.getValue(*BoundFooDecl, SkipPast::Reference); 3843 EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BoundFooValue); 3844 }); 3845 } 3846 // TODO: ref binding 3847 3848 TEST(TransferTest, BinaryOperatorComma) { 3849 std::string Code = R"( 3850 void target(int Foo, int Bar) { 3851 int &Baz = (Foo, Bar); 3852 // [[p]] 3853 } 3854 )"; 3855 runDataflow( 3856 Code, 3857 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3858 ASTContext &ASTCtx) { 3859 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3860 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3861 3862 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3863 ASSERT_THAT(BarDecl, NotNull()); 3864 3865 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3866 ASSERT_THAT(BazDecl, NotNull()); 3867 3868 const StorageLocation *BarLoc = 3869 Env.getStorageLocation(*BarDecl, SkipPast::Reference); 3870 ASSERT_THAT(BarLoc, NotNull()); 3871 3872 const StorageLocation *BazLoc = 3873 Env.getStorageLocation(*BazDecl, SkipPast::Reference); 3874 EXPECT_EQ(BazLoc, BarLoc); 3875 }); 3876 } 3877 3878 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) { 3879 std::string Code = R"( 3880 void target(bool Foo) { 3881 if (Foo) { 3882 (void)0; 3883 // [[if_then]] 3884 } else { 3885 (void)0; 3886 // [[if_else]] 3887 } 3888 } 3889 )"; 3890 runDataflow( 3891 Code, 3892 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3893 ASTContext &ASTCtx) { 3894 ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else")); 3895 const Environment &ThenEnv = 3896 getEnvironmentAtAnnotation(Results, "if_then"); 3897 const Environment &ElseEnv = 3898 getEnvironmentAtAnnotation(Results, "if_else"); 3899 3900 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3901 ASSERT_THAT(FooDecl, NotNull()); 3902 3903 BoolValue &ThenFooVal = 3904 *cast<BoolValue>(ThenEnv.getValue(*FooDecl, SkipPast::None)); 3905 EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal)); 3906 3907 BoolValue &ElseFooVal = 3908 *cast<BoolValue>(ElseEnv.getValue(*FooDecl, SkipPast::None)); 3909 EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal))); 3910 }); 3911 } 3912 3913 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) { 3914 std::string Code = R"( 3915 void target(bool Foo) { 3916 while (Foo) { 3917 (void)0; 3918 // [[loop_body]] 3919 } 3920 (void)0; 3921 // [[after_loop]] 3922 } 3923 )"; 3924 runDataflow( 3925 Code, 3926 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3927 ASTContext &ASTCtx) { 3928 ASSERT_THAT(Results.keys(), 3929 UnorderedElementsAre("loop_body", "after_loop")); 3930 const Environment &LoopBodyEnv = 3931 getEnvironmentAtAnnotation(Results, "loop_body"); 3932 const Environment &AfterLoopEnv = 3933 getEnvironmentAtAnnotation(Results, "after_loop"); 3934 3935 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3936 ASSERT_THAT(FooDecl, NotNull()); 3937 3938 BoolValue &LoopBodyFooVal = 3939 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 3940 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 3941 3942 BoolValue &AfterLoopFooVal = 3943 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None)); 3944 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 3945 AfterLoopEnv.makeNot(AfterLoopFooVal))); 3946 }); 3947 } 3948 3949 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) { 3950 std::string Code = R"( 3951 void target(bool Foo) { 3952 bool Bar = true; 3953 do { 3954 (void)0; 3955 // [[loop_body]] 3956 Bar = false; 3957 } while (Foo); 3958 (void)0; 3959 // [[after_loop]] 3960 } 3961 )"; 3962 runDataflow( 3963 Code, 3964 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3965 ASTContext &ASTCtx) { 3966 ASSERT_THAT(Results.keys(), 3967 UnorderedElementsAre("loop_body", "after_loop")); 3968 const Environment &LoopBodyEnv = 3969 getEnvironmentAtAnnotation(Results, "loop_body"); 3970 const Environment &AfterLoopEnv = 3971 getEnvironmentAtAnnotation(Results, "after_loop"); 3972 3973 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3974 ASSERT_THAT(FooDecl, NotNull()); 3975 3976 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3977 ASSERT_THAT(BarDecl, NotNull()); 3978 3979 BoolValue &LoopBodyFooVal = 3980 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 3981 BoolValue &LoopBodyBarVal = 3982 *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl, SkipPast::None)); 3983 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies( 3984 LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal))); 3985 3986 BoolValue &AfterLoopFooVal = 3987 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None)); 3988 BoolValue &AfterLoopBarVal = 3989 *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl, SkipPast::None)); 3990 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 3991 AfterLoopEnv.makeNot(AfterLoopFooVal))); 3992 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 3993 AfterLoopEnv.makeNot(AfterLoopBarVal))); 3994 }); 3995 } 3996 3997 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) { 3998 std::string Code = R"( 3999 void target(bool Foo) { 4000 for (; Foo;) { 4001 (void)0; 4002 // [[loop_body]] 4003 } 4004 (void)0; 4005 // [[after_loop]] 4006 } 4007 )"; 4008 runDataflow( 4009 Code, 4010 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4011 ASTContext &ASTCtx) { 4012 ASSERT_THAT(Results.keys(), 4013 UnorderedElementsAre("loop_body", "after_loop")); 4014 const Environment &LoopBodyEnv = 4015 getEnvironmentAtAnnotation(Results, "loop_body"); 4016 const Environment &AfterLoopEnv = 4017 getEnvironmentAtAnnotation(Results, "after_loop"); 4018 4019 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4020 ASSERT_THAT(FooDecl, NotNull()); 4021 4022 BoolValue &LoopBodyFooVal = 4023 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 4024 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4025 4026 BoolValue &AfterLoopFooVal = 4027 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None)); 4028 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4029 AfterLoopEnv.makeNot(AfterLoopFooVal))); 4030 }); 4031 } 4032 4033 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) { 4034 std::string Code = R"( 4035 void target(bool Foo) { 4036 for (;;) { 4037 (void)0; 4038 // [[loop_body]] 4039 } 4040 } 4041 )"; 4042 runDataflow( 4043 Code, 4044 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4045 ASTContext &ASTCtx) { 4046 ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body")); 4047 const Environment &LoopBodyEnv = 4048 getEnvironmentAtAnnotation(Results, "loop_body"); 4049 4050 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4051 ASSERT_THAT(FooDecl, NotNull()); 4052 4053 BoolValue &LoopBodyFooVal = 4054 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 4055 EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4056 }); 4057 } 4058 4059 TEST(TransferTest, ContextSensitiveOptionDisabled) { 4060 std::string Code = R"( 4061 bool GiveBool(); 4062 void SetBool(bool &Var) { Var = true; } 4063 4064 void target() { 4065 bool Foo = GiveBool(); 4066 SetBool(Foo); 4067 // [[p]] 4068 } 4069 )"; 4070 runDataflow( 4071 Code, 4072 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4073 ASTContext &ASTCtx) { 4074 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4075 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4076 4077 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4078 ASSERT_THAT(FooDecl, NotNull()); 4079 4080 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4081 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4082 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4083 }, 4084 {TransferOptions{/*.ContextSensitiveOpts=*/std::nullopt}}); 4085 } 4086 4087 // This test is a regression test, based on a real crash. 4088 TEST(TransferTest, ContextSensitiveReturnReferenceFromNonReferenceLvalue) { 4089 // This code exercises an unusual code path. If we return an lvalue directly, 4090 // the code will catch that it's an l-value based on the `Value`'s kind. If we 4091 // pass through a dummy function, the framework won't populate a value at 4092 // all. In contrast, this code results in a (fresh) value, but it is not 4093 // `ReferenceValue`. This test verifies that we catch this case as well. 4094 std::string Code = R"( 4095 class S {}; 4096 S& target(bool b, S &s) { 4097 return b ? s : s; 4098 // [[p]] 4099 } 4100 )"; 4101 runDataflow( 4102 Code, 4103 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4104 ASTContext &ASTCtx) { 4105 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4106 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4107 4108 auto *Loc = Env.getReturnStorageLocation(); 4109 ASSERT_THAT(Loc, NotNull()); 4110 4111 EXPECT_THAT(Env.getValue(*Loc), IsNull()); 4112 }, 4113 {TransferOptions{ContextSensitiveOptions{}}}); 4114 } 4115 4116 TEST(TransferTest, ContextSensitiveDepthZero) { 4117 std::string Code = R"( 4118 bool GiveBool(); 4119 void SetBool(bool &Var) { Var = true; } 4120 4121 void target() { 4122 bool Foo = GiveBool(); 4123 SetBool(Foo); 4124 // [[p]] 4125 } 4126 )"; 4127 runDataflow( 4128 Code, 4129 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4130 ASTContext &ASTCtx) { 4131 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4132 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4133 4134 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4135 ASSERT_THAT(FooDecl, NotNull()); 4136 4137 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4138 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4139 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4140 }, 4141 {TransferOptions{ContextSensitiveOptions{/*.Depth=*/0}}}); 4142 } 4143 4144 TEST(TransferTest, ContextSensitiveSetTrue) { 4145 std::string Code = R"( 4146 bool GiveBool(); 4147 void SetBool(bool &Var) { Var = true; } 4148 4149 void target() { 4150 bool Foo = GiveBool(); 4151 SetBool(Foo); 4152 // [[p]] 4153 } 4154 )"; 4155 runDataflow( 4156 Code, 4157 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4158 ASTContext &ASTCtx) { 4159 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4160 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4161 4162 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4163 ASSERT_THAT(FooDecl, NotNull()); 4164 4165 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4166 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4167 }, 4168 {TransferOptions{ContextSensitiveOptions{}}}); 4169 } 4170 4171 TEST(TransferTest, ContextSensitiveSetFalse) { 4172 std::string Code = R"( 4173 bool GiveBool(); 4174 void SetBool(bool &Var) { Var = false; } 4175 4176 void target() { 4177 bool Foo = GiveBool(); 4178 SetBool(Foo); 4179 // [[p]] 4180 } 4181 )"; 4182 runDataflow( 4183 Code, 4184 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4185 ASTContext &ASTCtx) { 4186 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4187 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4188 4189 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4190 ASSERT_THAT(FooDecl, NotNull()); 4191 4192 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4193 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4194 }, 4195 {TransferOptions{ContextSensitiveOptions{}}}); 4196 } 4197 4198 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) { 4199 std::string Code = R"( 4200 bool GiveBool(); 4201 void SetBool(bool &Var, bool Val) { Var = Val; } 4202 4203 void target() { 4204 bool Foo = GiveBool(); 4205 bool Bar = GiveBool(); 4206 SetBool(Foo, true); 4207 SetBool(Bar, false); 4208 // [[p]] 4209 } 4210 )"; 4211 runDataflow( 4212 Code, 4213 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4214 ASTContext &ASTCtx) { 4215 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4216 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4217 4218 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4219 ASSERT_THAT(FooDecl, NotNull()); 4220 4221 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4222 ASSERT_THAT(BarDecl, NotNull()); 4223 4224 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4225 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4226 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4227 4228 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 4229 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4230 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4231 }, 4232 {TransferOptions{ContextSensitiveOptions{}}}); 4233 } 4234 4235 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) { 4236 std::string Code = R"( 4237 bool GiveBool(); 4238 void SetBool1(bool &Var) { Var = true; } 4239 void SetBool2(bool &Var) { SetBool1(Var); } 4240 4241 void target() { 4242 bool Foo = GiveBool(); 4243 SetBool2(Foo); 4244 // [[p]] 4245 } 4246 )"; 4247 runDataflow( 4248 Code, 4249 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4250 ASTContext &ASTCtx) { 4251 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4252 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4253 4254 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4255 ASSERT_THAT(FooDecl, NotNull()); 4256 4257 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4258 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4259 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4260 }, 4261 {TransferOptions{ContextSensitiveOptions{/*.Depth=*/1}}}); 4262 } 4263 4264 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) { 4265 std::string Code = R"( 4266 bool GiveBool(); 4267 void SetBool1(bool &Var) { Var = true; } 4268 void SetBool2(bool &Var) { SetBool1(Var); } 4269 4270 void target() { 4271 bool Foo = GiveBool(); 4272 SetBool2(Foo); 4273 // [[p]] 4274 } 4275 )"; 4276 runDataflow( 4277 Code, 4278 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4279 ASTContext &ASTCtx) { 4280 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4281 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4282 4283 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4284 ASSERT_THAT(FooDecl, NotNull()); 4285 4286 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4287 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4288 }, 4289 {TransferOptions{ContextSensitiveOptions{/*.Depth=*/2}}}); 4290 } 4291 4292 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) { 4293 std::string Code = R"( 4294 bool GiveBool(); 4295 void SetBool1(bool &Var) { Var = true; } 4296 void SetBool2(bool &Var) { SetBool1(Var); } 4297 void SetBool3(bool &Var) { SetBool2(Var); } 4298 4299 void target() { 4300 bool Foo = GiveBool(); 4301 SetBool3(Foo); 4302 // [[p]] 4303 } 4304 )"; 4305 runDataflow( 4306 Code, 4307 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4308 ASTContext &ASTCtx) { 4309 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4310 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4311 4312 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4313 ASSERT_THAT(FooDecl, NotNull()); 4314 4315 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4316 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4317 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4318 }, 4319 {TransferOptions{ContextSensitiveOptions{/*.Depth=*/2}}}); 4320 } 4321 4322 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) { 4323 std::string Code = R"( 4324 bool GiveBool(); 4325 void SetBool1(bool &Var) { Var = true; } 4326 void SetBool2(bool &Var) { SetBool1(Var); } 4327 void SetBool3(bool &Var) { SetBool2(Var); } 4328 4329 void target() { 4330 bool Foo = GiveBool(); 4331 SetBool3(Foo); 4332 // [[p]] 4333 } 4334 )"; 4335 runDataflow( 4336 Code, 4337 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4338 ASTContext &ASTCtx) { 4339 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4340 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4341 4342 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4343 ASSERT_THAT(FooDecl, NotNull()); 4344 4345 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4346 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4347 }, 4348 {TransferOptions{ContextSensitiveOptions{/*.Depth=*/3}}}); 4349 } 4350 4351 TEST(TransferTest, ContextSensitiveMutualRecursion) { 4352 std::string Code = R"( 4353 bool Pong(bool X, bool Y); 4354 4355 bool Ping(bool X, bool Y) { 4356 if (X) { 4357 return Y; 4358 } else { 4359 return Pong(!X, Y); 4360 } 4361 } 4362 4363 bool Pong(bool X, bool Y) { 4364 if (Y) { 4365 return X; 4366 } else { 4367 return Ping(X, !Y); 4368 } 4369 } 4370 4371 void target() { 4372 bool Foo = Ping(false, false); 4373 // [[p]] 4374 } 4375 )"; 4376 runDataflow( 4377 Code, 4378 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4379 ASTContext &ASTCtx) { 4380 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4381 // The analysis doesn't crash... 4382 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4383 4384 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4385 ASSERT_THAT(FooDecl, NotNull()); 4386 4387 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4388 // ... but it also can't prove anything here. 4389 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4390 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4391 }, 4392 {TransferOptions{ContextSensitiveOptions{/*.Depth=*/4}}}); 4393 } 4394 4395 TEST(TransferTest, ContextSensitiveSetMultipleLines) { 4396 std::string Code = R"( 4397 void SetBools(bool &Var1, bool &Var2) { 4398 Var1 = true; 4399 Var2 = false; 4400 } 4401 4402 void target() { 4403 bool Foo = false; 4404 bool Bar = true; 4405 SetBools(Foo, Bar); 4406 // [[p]] 4407 } 4408 )"; 4409 runDataflow( 4410 Code, 4411 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4412 ASTContext &ASTCtx) { 4413 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4414 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4415 4416 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4417 ASSERT_THAT(FooDecl, NotNull()); 4418 4419 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4420 ASSERT_THAT(BarDecl, NotNull()); 4421 4422 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4423 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4424 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4425 4426 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 4427 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4428 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4429 }, 4430 {TransferOptions{ContextSensitiveOptions{}}}); 4431 } 4432 4433 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) { 4434 std::string Code = R"( 4435 void IfCond(bool Cond, bool &Then, bool &Else) { 4436 if (Cond) { 4437 Then = true; 4438 } else { 4439 Else = true; 4440 } 4441 } 4442 4443 void target() { 4444 bool Foo = false; 4445 bool Bar = false; 4446 bool Baz = false; 4447 IfCond(Foo, Bar, Baz); 4448 // [[p]] 4449 } 4450 )"; 4451 runDataflow( 4452 Code, 4453 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4454 ASTContext &ASTCtx) { 4455 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4456 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4457 4458 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4459 ASSERT_THAT(BarDecl, NotNull()); 4460 4461 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4462 ASSERT_THAT(BazDecl, NotNull()); 4463 4464 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 4465 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4466 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4467 4468 auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl, SkipPast::None)); 4469 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 4470 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal))); 4471 }, 4472 {TransferOptions{ContextSensitiveOptions{}}}); 4473 } 4474 4475 TEST(TransferTest, ContextSensitiveReturnVoid) { 4476 std::string Code = R"( 4477 void Noop() { return; } 4478 4479 void target() { 4480 Noop(); 4481 // [[p]] 4482 } 4483 )"; 4484 runDataflow( 4485 Code, 4486 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4487 ASTContext &ASTCtx) { 4488 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4489 // This just tests that the analysis doesn't crash. 4490 }, 4491 {TransferOptions{ContextSensitiveOptions{}}}); 4492 } 4493 4494 TEST(TransferTest, ContextSensitiveReturnTrue) { 4495 std::string Code = R"( 4496 bool GiveBool() { return true; } 4497 4498 void target() { 4499 bool Foo = GiveBool(); 4500 // [[p]] 4501 } 4502 )"; 4503 runDataflow( 4504 Code, 4505 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4506 ASTContext &ASTCtx) { 4507 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4508 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4509 4510 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4511 ASSERT_THAT(FooDecl, NotNull()); 4512 4513 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4514 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4515 }, 4516 {TransferOptions{ContextSensitiveOptions{}}}); 4517 } 4518 4519 TEST(TransferTest, ContextSensitiveReturnFalse) { 4520 std::string Code = R"( 4521 bool GiveBool() { return false; } 4522 4523 void target() { 4524 bool Foo = GiveBool(); 4525 // [[p]] 4526 } 4527 )"; 4528 runDataflow( 4529 Code, 4530 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4531 ASTContext &ASTCtx) { 4532 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4533 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4534 4535 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4536 ASSERT_THAT(FooDecl, NotNull()); 4537 4538 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4539 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4540 }, 4541 {TransferOptions{ContextSensitiveOptions{}}}); 4542 } 4543 4544 TEST(TransferTest, ContextSensitiveReturnArg) { 4545 std::string Code = R"( 4546 bool GiveBool(); 4547 bool GiveBack(bool Arg) { return Arg; } 4548 4549 void target() { 4550 bool Foo = GiveBool(); 4551 bool Bar = GiveBack(Foo); 4552 bool Baz = Foo == Bar; 4553 // [[p]] 4554 } 4555 )"; 4556 runDataflow( 4557 Code, 4558 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4559 ASTContext &ASTCtx) { 4560 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4561 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4562 4563 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4564 ASSERT_THAT(BazDecl, NotNull()); 4565 4566 auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl, SkipPast::None)); 4567 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 4568 }, 4569 {TransferOptions{ContextSensitiveOptions{}}}); 4570 } 4571 4572 TEST(TransferTest, ContextSensitiveReturnInt) { 4573 std::string Code = R"( 4574 int identity(int x) { return x; } 4575 4576 void target() { 4577 int y = identity(42); 4578 // [[p]] 4579 } 4580 )"; 4581 runDataflow( 4582 Code, 4583 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4584 ASTContext &ASTCtx) { 4585 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4586 // This just tests that the analysis doesn't crash. 4587 }, 4588 {TransferOptions{ContextSensitiveOptions{}}}); 4589 } 4590 4591 TEST(TransferTest, ContextSensitiveMethodLiteral) { 4592 std::string Code = R"( 4593 class MyClass { 4594 public: 4595 bool giveBool() { return true; } 4596 }; 4597 4598 void target() { 4599 MyClass MyObj; 4600 bool Foo = MyObj.giveBool(); 4601 // [[p]] 4602 } 4603 )"; 4604 runDataflow( 4605 Code, 4606 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4607 ASTContext &ASTCtx) { 4608 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4609 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4610 4611 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4612 ASSERT_THAT(FooDecl, NotNull()); 4613 4614 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4615 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4616 }, 4617 {TransferOptions{ContextSensitiveOptions{}}}); 4618 } 4619 4620 TEST(TransferTest, ContextSensitiveMethodGetter) { 4621 std::string Code = R"( 4622 class MyClass { 4623 public: 4624 bool getField() { return Field; } 4625 4626 bool Field; 4627 }; 4628 4629 void target() { 4630 MyClass MyObj; 4631 MyObj.Field = true; 4632 bool Foo = MyObj.getField(); 4633 // [[p]] 4634 } 4635 )"; 4636 runDataflow( 4637 Code, 4638 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4639 ASTContext &ASTCtx) { 4640 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4641 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4642 4643 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4644 ASSERT_THAT(FooDecl, NotNull()); 4645 4646 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4647 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4648 }, 4649 {TransferOptions{ContextSensitiveOptions{}}}); 4650 } 4651 4652 TEST(TransferTest, ContextSensitiveMethodSetter) { 4653 std::string Code = R"( 4654 class MyClass { 4655 public: 4656 void setField(bool Val) { Field = Val; } 4657 4658 bool Field; 4659 }; 4660 4661 void target() { 4662 MyClass MyObj; 4663 MyObj.setField(true); 4664 bool Foo = MyObj.Field; 4665 // [[p]] 4666 } 4667 )"; 4668 runDataflow( 4669 Code, 4670 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4671 ASTContext &ASTCtx) { 4672 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4673 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4674 4675 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4676 ASSERT_THAT(FooDecl, NotNull()); 4677 4678 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4679 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4680 }, 4681 {TransferOptions{ContextSensitiveOptions{}}}); 4682 } 4683 4684 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) { 4685 std::string Code = R"( 4686 class MyClass { 4687 public: 4688 bool getField() { return Field; } 4689 void setField(bool Val) { Field = Val; } 4690 4691 private: 4692 bool Field; 4693 }; 4694 4695 void target() { 4696 MyClass MyObj; 4697 MyObj.setField(true); 4698 bool Foo = MyObj.getField(); 4699 // [[p]] 4700 } 4701 )"; 4702 runDataflow( 4703 Code, 4704 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4705 ASTContext &ASTCtx) { 4706 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4707 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4708 4709 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4710 ASSERT_THAT(FooDecl, NotNull()); 4711 4712 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4713 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4714 }, 4715 {TransferOptions{ContextSensitiveOptions{}}}); 4716 } 4717 4718 4719 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) { 4720 std::string Code = R"( 4721 class MyClass { 4722 public: 4723 void Inner() { MyField = true; } 4724 void Outer() { Inner(); } 4725 4726 bool MyField; 4727 }; 4728 4729 void target() { 4730 MyClass MyObj; 4731 MyObj.Outer(); 4732 bool Foo = MyObj.MyField; 4733 // [[p]] 4734 } 4735 )"; 4736 runDataflow( 4737 Code, 4738 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4739 ASTContext &ASTCtx) { 4740 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));; 4741 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4742 4743 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4744 ASSERT_THAT(FooDecl, NotNull()); 4745 4746 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4747 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4748 }, 4749 {TransferOptions{ContextSensitiveOptions{}}}); 4750 } 4751 4752 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) { 4753 std::string Code = R"( 4754 class MyClass { 4755 public: 4756 bool Inner() { return MyField; } 4757 bool Outer() { return Inner(); } 4758 4759 bool MyField; 4760 }; 4761 4762 void target() { 4763 MyClass MyObj; 4764 MyObj.MyField = true; 4765 bool Foo = MyObj.Outer(); 4766 // [[p]] 4767 } 4768 )"; 4769 runDataflow( 4770 Code, 4771 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4772 ASTContext &ASTCtx) { 4773 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));; 4774 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4775 4776 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4777 ASSERT_THAT(FooDecl, NotNull()); 4778 4779 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4780 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4781 }, 4782 {TransferOptions{ContextSensitiveOptions{}}}); 4783 } 4784 4785 TEST(TransferTest, ContextSensitiveConstructorBody) { 4786 std::string Code = R"( 4787 class MyClass { 4788 public: 4789 MyClass() { MyField = true; } 4790 4791 bool MyField; 4792 }; 4793 4794 void target() { 4795 MyClass MyObj; 4796 bool Foo = MyObj.MyField; 4797 // [[p]] 4798 } 4799 )"; 4800 runDataflow( 4801 Code, 4802 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4803 ASTContext &ASTCtx) { 4804 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4805 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4806 4807 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4808 ASSERT_THAT(FooDecl, NotNull()); 4809 4810 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4811 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4812 }, 4813 {TransferOptions{ContextSensitiveOptions{}}}); 4814 } 4815 4816 TEST(TransferTest, ContextSensitiveConstructorInitializer) { 4817 std::string Code = R"( 4818 class MyClass { 4819 public: 4820 MyClass() : MyField(true) {} 4821 4822 bool MyField; 4823 }; 4824 4825 void target() { 4826 MyClass MyObj; 4827 bool Foo = MyObj.MyField; 4828 // [[p]] 4829 } 4830 )"; 4831 runDataflow( 4832 Code, 4833 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4834 ASTContext &ASTCtx) { 4835 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4836 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4837 4838 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4839 ASSERT_THAT(FooDecl, NotNull()); 4840 4841 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4842 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4843 }, 4844 {TransferOptions{ContextSensitiveOptions{}}}); 4845 } 4846 4847 TEST(TransferTest, ContextSensitiveConstructorDefault) { 4848 std::string Code = R"( 4849 class MyClass { 4850 public: 4851 MyClass() = default; 4852 4853 bool MyField = true; 4854 }; 4855 4856 void target() { 4857 MyClass MyObj; 4858 bool Foo = MyObj.MyField; 4859 // [[p]] 4860 } 4861 )"; 4862 runDataflow( 4863 Code, 4864 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4865 ASTContext &ASTCtx) { 4866 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4867 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4868 4869 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4870 ASSERT_THAT(FooDecl, NotNull()); 4871 4872 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4873 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4874 }, 4875 {TransferOptions{ContextSensitiveOptions{}}}); 4876 } 4877 4878 } // namespace 4879