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