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