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