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(Code), 2671 llvm::FailedWithMessage("Cannot analyze templated declarations")); 2672 } 2673 2674 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) { 2675 std::string Code = R"( 2676 template <typename T> 2677 struct A { 2678 void target() {} 2679 }; 2680 )"; 2681 ASSERT_THAT_ERROR( 2682 checkDataflowWithNoopAnalysis(Code), 2683 llvm::FailedWithMessage("Cannot analyze templated declarations")); 2684 } 2685 2686 TEST(TransferTest, VarDeclInitAssignConditionalOperator) { 2687 std::string Code = R"( 2688 struct A {}; 2689 2690 void target(A Foo, A Bar, bool Cond) { 2691 A Baz = Cond ? Foo : Bar; 2692 /*[[p]]*/ 2693 } 2694 )"; 2695 runDataflow( 2696 Code, 2697 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2698 ASTContext &ASTCtx) { 2699 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2700 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2701 2702 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2703 ASSERT_THAT(FooDecl, NotNull()); 2704 2705 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2706 ASSERT_THAT(BarDecl, NotNull()); 2707 2708 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2709 ASSERT_THAT(BazDecl, NotNull()); 2710 2711 const auto *FooVal = cast<RecordValue>(Env.getValue(*FooDecl)); 2712 const auto *BarVal = cast<RecordValue>(Env.getValue(*BarDecl)); 2713 2714 const auto *BazVal = dyn_cast<RecordValue>(Env.getValue(*BazDecl)); 2715 ASSERT_THAT(BazVal, NotNull()); 2716 2717 EXPECT_NE(BazVal, FooVal); 2718 EXPECT_NE(BazVal, BarVal); 2719 }); 2720 } 2721 2722 TEST(TransferTest, VarDeclInDoWhile) { 2723 std::string Code = R"( 2724 void target(int *Foo) { 2725 do { 2726 int Bar = *Foo; 2727 // [[in_loop]] 2728 } while (false); 2729 (void)0; 2730 // [[after_loop]] 2731 } 2732 )"; 2733 runDataflow( 2734 Code, 2735 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2736 ASTContext &ASTCtx) { 2737 const Environment &EnvInLoop = 2738 getEnvironmentAtAnnotation(Results, "in_loop"); 2739 const Environment &EnvAfterLoop = 2740 getEnvironmentAtAnnotation(Results, "after_loop"); 2741 2742 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2743 ASSERT_THAT(FooDecl, NotNull()); 2744 2745 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2746 ASSERT_THAT(BarDecl, NotNull()); 2747 2748 const auto *FooVal = 2749 cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl)); 2750 const auto *FooPointeeVal = 2751 cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc())); 2752 2753 const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl)); 2754 EXPECT_EQ(BarVal, FooPointeeVal); 2755 2756 // FIXME: This assertion documents current behavior, but we would prefer 2757 // declarations to be removed from the environment when their lifetime 2758 // ends. Once this is the case, change this assertion accordingly. 2759 ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), BarVal); 2760 }); 2761 } 2762 2763 TEST(TransferTest, UnreachableAfterWhileTrue) { 2764 std::string Code = R"( 2765 void target() { 2766 while (true) {} 2767 (void)0; 2768 /*[[p]]*/ 2769 } 2770 )"; 2771 runDataflow( 2772 Code, 2773 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2774 ASTContext &ASTCtx) { 2775 // The node after the while-true is pruned because it is trivially 2776 // known to be unreachable. 2777 ASSERT_TRUE(Results.empty()); 2778 }); 2779 } 2780 2781 TEST(TransferTest, AggregateInitialization) { 2782 std::string BracesCode = R"( 2783 struct A { 2784 int Foo; 2785 }; 2786 2787 struct B { 2788 int Bar; 2789 A Baz; 2790 int Qux; 2791 }; 2792 2793 void target(int BarArg, int FooArg, int QuxArg) { 2794 B Quux{BarArg, {FooArg}, QuxArg}; 2795 B OtherB; 2796 /*[[p]]*/ 2797 } 2798 )"; 2799 std::string BraceElisionCode = R"( 2800 struct A { 2801 int Foo; 2802 }; 2803 2804 struct B { 2805 int Bar; 2806 A Baz; 2807 int Qux; 2808 }; 2809 2810 void target(int BarArg, int FooArg, int QuxArg) { 2811 B Quux = {BarArg, FooArg, QuxArg}; 2812 B OtherB; 2813 /*[[p]]*/ 2814 } 2815 )"; 2816 for (const std::string &Code : {BracesCode, BraceElisionCode}) { 2817 runDataflow( 2818 Code, 2819 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2820 ASTContext &ASTCtx) { 2821 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2822 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2823 2824 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2825 ASSERT_THAT(FooDecl, NotNull()); 2826 2827 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2828 ASSERT_THAT(BarDecl, NotNull()); 2829 2830 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2831 ASSERT_THAT(BazDecl, NotNull()); 2832 2833 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2834 ASSERT_THAT(QuxDecl, NotNull()); 2835 2836 const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg"); 2837 ASSERT_THAT(FooArgDecl, NotNull()); 2838 2839 const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg"); 2840 ASSERT_THAT(BarArgDecl, NotNull()); 2841 2842 const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg"); 2843 ASSERT_THAT(QuxArgDecl, NotNull()); 2844 2845 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 2846 ASSERT_THAT(QuuxDecl, NotNull()); 2847 2848 const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl)); 2849 const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl)); 2850 const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl)); 2851 2852 const auto *QuuxVal = cast<RecordValue>(Env.getValue(*QuuxDecl)); 2853 ASSERT_THAT(QuuxVal, NotNull()); 2854 2855 const auto *BazVal = 2856 cast<RecordValue>(getFieldValue(QuuxVal, *BazDecl, Env)); 2857 ASSERT_THAT(BazVal, NotNull()); 2858 2859 EXPECT_EQ(getFieldValue(QuuxVal, *BarDecl, Env), BarArgVal); 2860 EXPECT_EQ(getFieldValue(BazVal, *FooDecl, Env), FooArgVal); 2861 EXPECT_EQ(getFieldValue(QuuxVal, *QuxDecl, Env), QuxArgVal); 2862 2863 // Check that fields initialized in an initializer list are always 2864 // modeled in other instances of the same type. 2865 const auto &OtherBVal = 2866 getValueForDecl<RecordValue>(ASTCtx, Env, "OtherB"); 2867 EXPECT_THAT(OtherBVal.getChild(*BarDecl), NotNull()); 2868 EXPECT_THAT(OtherBVal.getChild(*BazDecl), NotNull()); 2869 EXPECT_THAT(OtherBVal.getChild(*QuxDecl), NotNull()); 2870 }); 2871 } 2872 } 2873 2874 TEST(TransferTest, AggregateInitializationReferenceField) { 2875 std::string Code = R"( 2876 struct S { 2877 int &RefField; 2878 }; 2879 2880 void target(int i) { 2881 S s = { i }; 2882 /*[[p]]*/ 2883 } 2884 )"; 2885 runDataflow( 2886 Code, 2887 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2888 ASTContext &ASTCtx) { 2889 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2890 2891 const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField"); 2892 2893 auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i"); 2894 auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"); 2895 2896 EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc); 2897 }); 2898 } 2899 2900 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) { 2901 std::string Code = R"( 2902 struct S { 2903 int i1; 2904 int i2; 2905 }; 2906 2907 void target(int i) { 2908 S s = { i }; 2909 /*[[p]]*/ 2910 } 2911 )"; 2912 runDataflow( 2913 Code, 2914 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2915 ASTContext &ASTCtx) { 2916 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2917 2918 const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1"); 2919 const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2"); 2920 2921 auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"); 2922 2923 auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i"); 2924 auto &I1Value = 2925 *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env)); 2926 EXPECT_EQ(&I1Value, &IValue); 2927 auto &I2Value = 2928 *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env)); 2929 EXPECT_NE(&I2Value, &IValue); 2930 }); 2931 } 2932 2933 TEST(TransferTest, AssignToUnionMember) { 2934 std::string Code = R"( 2935 union A { 2936 int Foo; 2937 }; 2938 2939 void target(int Bar) { 2940 A Baz; 2941 Baz.Foo = Bar; 2942 // [[p]] 2943 } 2944 )"; 2945 runDataflow( 2946 Code, 2947 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2948 ASTContext &ASTCtx) { 2949 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2950 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2951 2952 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2953 ASSERT_THAT(BazDecl, NotNull()); 2954 ASSERT_TRUE(BazDecl->getType()->isUnionType()); 2955 2956 auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields(); 2957 FieldDecl *FooDecl = nullptr; 2958 for (FieldDecl *Field : BazFields) { 2959 if (Field->getNameAsString() == "Foo") { 2960 FooDecl = Field; 2961 } else { 2962 FAIL() << "Unexpected field: " << Field->getNameAsString(); 2963 } 2964 } 2965 ASSERT_THAT(FooDecl, NotNull()); 2966 2967 const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>( 2968 Env.getStorageLocation(*BazDecl)); 2969 ASSERT_THAT(BazLoc, NotNull()); 2970 ASSERT_THAT(Env.getValue(*BazLoc), NotNull()); 2971 2972 const auto *FooVal = 2973 cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env)); 2974 2975 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2976 ASSERT_THAT(BarDecl, NotNull()); 2977 const auto *BarLoc = Env.getStorageLocation(*BarDecl); 2978 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 2979 2980 EXPECT_EQ(Env.getValue(*BarLoc), FooVal); 2981 }); 2982 } 2983 2984 TEST(TransferTest, AssignFromBoolLiteral) { 2985 std::string Code = R"( 2986 void target() { 2987 bool Foo = true; 2988 bool Bar = false; 2989 // [[p]] 2990 } 2991 )"; 2992 runDataflow( 2993 Code, 2994 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2995 ASTContext &ASTCtx) { 2996 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2997 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2998 2999 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3000 ASSERT_THAT(FooDecl, NotNull()); 3001 3002 const auto *FooVal = 3003 dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl)); 3004 ASSERT_THAT(FooVal, NotNull()); 3005 3006 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3007 ASSERT_THAT(BarDecl, NotNull()); 3008 3009 const auto *BarVal = 3010 dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*BarDecl)); 3011 ASSERT_THAT(BarVal, NotNull()); 3012 3013 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true)); 3014 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false)); 3015 }); 3016 } 3017 3018 TEST(TransferTest, AssignFromCompositeBoolExpression) { 3019 { 3020 std::string Code = R"( 3021 void target(bool Foo, bool Bar, bool Qux) { 3022 bool Baz = (Foo) && (Bar || Qux); 3023 // [[p]] 3024 } 3025 )"; 3026 runDataflow( 3027 Code, 3028 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3029 ASTContext &ASTCtx) { 3030 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3031 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3032 3033 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3034 ASSERT_THAT(FooDecl, NotNull()); 3035 3036 const auto *FooVal = 3037 dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl)); 3038 ASSERT_THAT(FooVal, NotNull()); 3039 3040 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3041 ASSERT_THAT(BarDecl, NotNull()); 3042 3043 const auto *BarVal = 3044 dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl)); 3045 ASSERT_THAT(BarVal, NotNull()); 3046 3047 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3048 ASSERT_THAT(QuxDecl, NotNull()); 3049 3050 const auto *QuxVal = 3051 dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl)); 3052 ASSERT_THAT(QuxVal, NotNull()); 3053 3054 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3055 ASSERT_THAT(BazDecl, NotNull()); 3056 3057 const auto *BazVal = 3058 dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl)); 3059 ASSERT_THAT(BazVal, NotNull()); 3060 auto &A = Env.arena(); 3061 EXPECT_EQ(&BazVal->formula(), 3062 &A.makeAnd(FooVal->formula(), 3063 A.makeOr(BarVal->formula(), QuxVal->formula()))); 3064 }); 3065 } 3066 3067 { 3068 std::string Code = R"( 3069 void target(bool Foo, bool Bar, bool Qux) { 3070 bool Baz = (Foo && Qux) || (Bar); 3071 // [[p]] 3072 } 3073 )"; 3074 runDataflow( 3075 Code, 3076 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3077 ASTContext &ASTCtx) { 3078 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3079 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3080 3081 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3082 ASSERT_THAT(FooDecl, NotNull()); 3083 3084 const auto *FooVal = 3085 dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl)); 3086 ASSERT_THAT(FooVal, NotNull()); 3087 3088 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3089 ASSERT_THAT(BarDecl, NotNull()); 3090 3091 const auto *BarVal = 3092 dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl)); 3093 ASSERT_THAT(BarVal, NotNull()); 3094 3095 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3096 ASSERT_THAT(QuxDecl, NotNull()); 3097 3098 const auto *QuxVal = 3099 dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl)); 3100 ASSERT_THAT(QuxVal, NotNull()); 3101 3102 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3103 ASSERT_THAT(BazDecl, NotNull()); 3104 3105 const auto *BazVal = 3106 dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl)); 3107 ASSERT_THAT(BazVal, NotNull()); 3108 auto &A = Env.arena(); 3109 EXPECT_EQ(&BazVal->formula(), 3110 &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()), 3111 BarVal->formula())); 3112 }); 3113 } 3114 3115 { 3116 std::string Code = R"( 3117 void target(bool A, bool B, bool C, bool D) { 3118 bool Foo = ((A && B) && C) && D; 3119 // [[p]] 3120 } 3121 )"; 3122 runDataflow( 3123 Code, 3124 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3125 ASTContext &ASTCtx) { 3126 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3127 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3128 3129 const ValueDecl *ADecl = findValueDecl(ASTCtx, "A"); 3130 ASSERT_THAT(ADecl, NotNull()); 3131 3132 const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl)); 3133 ASSERT_THAT(AVal, NotNull()); 3134 3135 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3136 ASSERT_THAT(BDecl, NotNull()); 3137 3138 const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl)); 3139 ASSERT_THAT(BVal, NotNull()); 3140 3141 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3142 ASSERT_THAT(CDecl, NotNull()); 3143 3144 const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl)); 3145 ASSERT_THAT(CVal, NotNull()); 3146 3147 const ValueDecl *DDecl = findValueDecl(ASTCtx, "D"); 3148 ASSERT_THAT(DDecl, NotNull()); 3149 3150 const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl)); 3151 ASSERT_THAT(DVal, NotNull()); 3152 3153 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3154 ASSERT_THAT(FooDecl, NotNull()); 3155 3156 const auto *FooVal = 3157 dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl)); 3158 ASSERT_THAT(FooVal, NotNull()); 3159 auto &A = Env.arena(); 3160 EXPECT_EQ( 3161 &FooVal->formula(), 3162 &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()), 3163 CVal->formula()), 3164 DVal->formula())); 3165 }); 3166 } 3167 } 3168 3169 TEST(TransferTest, AssignFromBoolNegation) { 3170 std::string Code = R"( 3171 void target() { 3172 bool Foo = true; 3173 bool Bar = !(Foo); 3174 // [[p]] 3175 } 3176 )"; 3177 runDataflow( 3178 Code, 3179 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3180 ASTContext &ASTCtx) { 3181 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3182 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3183 3184 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3185 ASSERT_THAT(FooDecl, NotNull()); 3186 3187 const auto *FooVal = 3188 dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl)); 3189 ASSERT_THAT(FooVal, NotNull()); 3190 3191 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3192 ASSERT_THAT(BarDecl, NotNull()); 3193 3194 const auto *BarVal = 3195 dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl)); 3196 ASSERT_THAT(BarVal, NotNull()); 3197 auto &A = Env.arena(); 3198 EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula())); 3199 }); 3200 } 3201 3202 TEST(TransferTest, BuiltinExpect) { 3203 std::string Code = R"( 3204 void target(long Foo) { 3205 long Bar = __builtin_expect(Foo, true); 3206 /*[[p]]*/ 3207 } 3208 )"; 3209 runDataflow( 3210 Code, 3211 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3212 ASTContext &ASTCtx) { 3213 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3214 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3215 3216 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3217 ASSERT_THAT(FooDecl, NotNull()); 3218 3219 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3220 ASSERT_THAT(BarDecl, NotNull()); 3221 3222 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3223 }); 3224 } 3225 3226 // `__builtin_expect` takes and returns a `long` argument, so other types 3227 // involve casts. This verifies that we identify the input and output in that 3228 // case. 3229 TEST(TransferTest, BuiltinExpectBoolArg) { 3230 std::string Code = R"( 3231 void target(bool Foo) { 3232 bool Bar = __builtin_expect(Foo, true); 3233 /*[[p]]*/ 3234 } 3235 )"; 3236 runDataflow( 3237 Code, 3238 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3239 ASTContext &ASTCtx) { 3240 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3241 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3242 3243 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3244 ASSERT_THAT(FooDecl, NotNull()); 3245 3246 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3247 ASSERT_THAT(BarDecl, NotNull()); 3248 3249 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3250 }); 3251 } 3252 3253 TEST(TransferTest, BuiltinUnreachable) { 3254 std::string Code = R"( 3255 void target(bool Foo) { 3256 bool Bar = false; 3257 if (Foo) 3258 Bar = Foo; 3259 else 3260 __builtin_unreachable(); 3261 (void)0; 3262 /*[[p]]*/ 3263 } 3264 )"; 3265 runDataflow( 3266 Code, 3267 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3268 ASTContext &ASTCtx) { 3269 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3270 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3271 3272 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3273 ASSERT_THAT(FooDecl, NotNull()); 3274 3275 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3276 ASSERT_THAT(BarDecl, NotNull()); 3277 3278 // `__builtin_unreachable` promises that the code is 3279 // unreachable, so the compiler treats the "then" branch as the 3280 // only possible predecessor of this statement. 3281 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3282 }); 3283 } 3284 3285 TEST(TransferTest, BuiltinTrap) { 3286 std::string Code = R"( 3287 void target(bool Foo) { 3288 bool Bar = false; 3289 if (Foo) 3290 Bar = Foo; 3291 else 3292 __builtin_trap(); 3293 (void)0; 3294 /*[[p]]*/ 3295 } 3296 )"; 3297 runDataflow( 3298 Code, 3299 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3300 ASTContext &ASTCtx) { 3301 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3302 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3303 3304 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3305 ASSERT_THAT(FooDecl, NotNull()); 3306 3307 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3308 ASSERT_THAT(BarDecl, NotNull()); 3309 3310 // `__builtin_trap` ensures program termination, so only the 3311 // "then" branch is a predecessor of this statement. 3312 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3313 }); 3314 } 3315 3316 TEST(TransferTest, BuiltinDebugTrap) { 3317 std::string Code = R"( 3318 void target(bool Foo) { 3319 bool Bar = false; 3320 if (Foo) 3321 Bar = Foo; 3322 else 3323 __builtin_debugtrap(); 3324 (void)0; 3325 /*[[p]]*/ 3326 } 3327 )"; 3328 runDataflow( 3329 Code, 3330 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3331 ASTContext &ASTCtx) { 3332 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3333 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3334 3335 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3336 ASSERT_THAT(FooDecl, NotNull()); 3337 3338 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3339 ASSERT_THAT(BarDecl, NotNull()); 3340 3341 // `__builtin_debugtrap` doesn't ensure program termination. 3342 EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3343 }); 3344 } 3345 3346 TEST(TransferTest, StaticIntSingleVarDecl) { 3347 std::string Code = R"( 3348 void target() { 3349 static int Foo; 3350 // [[p]] 3351 } 3352 )"; 3353 runDataflow( 3354 Code, 3355 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3356 ASTContext &ASTCtx) { 3357 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3358 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3359 3360 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3361 ASSERT_THAT(FooDecl, NotNull()); 3362 3363 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 3364 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3365 3366 const Value *FooVal = Env.getValue(*FooLoc); 3367 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3368 }); 3369 } 3370 3371 TEST(TransferTest, StaticIntGroupVarDecl) { 3372 std::string Code = R"( 3373 void target() { 3374 static int Foo, Bar; 3375 (void)0; 3376 // [[p]] 3377 } 3378 )"; 3379 runDataflow( 3380 Code, 3381 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3382 ASTContext &ASTCtx) { 3383 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3384 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3385 3386 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3387 ASSERT_THAT(FooDecl, NotNull()); 3388 3389 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3390 ASSERT_THAT(BarDecl, NotNull()); 3391 3392 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 3393 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3394 3395 const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl); 3396 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 3397 3398 const Value *FooVal = Env.getValue(*FooLoc); 3399 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3400 3401 const Value *BarVal = Env.getValue(*BarLoc); 3402 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 3403 3404 EXPECT_NE(FooVal, BarVal); 3405 }); 3406 } 3407 3408 TEST(TransferTest, GlobalIntVarDecl) { 3409 std::string Code = R"( 3410 static int Foo; 3411 3412 void target() { 3413 int Bar = Foo; 3414 int Baz = Foo; 3415 // [[p]] 3416 } 3417 )"; 3418 runDataflow( 3419 Code, 3420 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3421 ASTContext &ASTCtx) { 3422 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3423 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3424 3425 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3426 ASSERT_THAT(BarDecl, NotNull()); 3427 3428 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3429 ASSERT_THAT(BazDecl, NotNull()); 3430 3431 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3432 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3433 EXPECT_EQ(BarVal, BazVal); 3434 }); 3435 } 3436 3437 TEST(TransferTest, StaticMemberIntVarDecl) { 3438 std::string Code = R"( 3439 struct A { 3440 static int Foo; 3441 }; 3442 3443 void target(A a) { 3444 int Bar = a.Foo; 3445 int Baz = a.Foo; 3446 // [[p]] 3447 } 3448 )"; 3449 runDataflow( 3450 Code, 3451 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3452 ASTContext &ASTCtx) { 3453 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3454 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3455 3456 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3457 ASSERT_THAT(BarDecl, NotNull()); 3458 3459 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3460 ASSERT_THAT(BazDecl, NotNull()); 3461 3462 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3463 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3464 EXPECT_EQ(BarVal, BazVal); 3465 }); 3466 } 3467 3468 TEST(TransferTest, StaticMemberRefVarDecl) { 3469 std::string Code = R"( 3470 struct A { 3471 static int &Foo; 3472 }; 3473 3474 void target(A a) { 3475 int Bar = a.Foo; 3476 int Baz = a.Foo; 3477 // [[p]] 3478 } 3479 )"; 3480 runDataflow( 3481 Code, 3482 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3483 ASTContext &ASTCtx) { 3484 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3485 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3486 3487 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3488 ASSERT_THAT(BarDecl, NotNull()); 3489 3490 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3491 ASSERT_THAT(BazDecl, NotNull()); 3492 3493 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3494 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3495 EXPECT_EQ(BarVal, BazVal); 3496 }); 3497 } 3498 3499 TEST(TransferTest, AssignMemberBeforeCopy) { 3500 std::string Code = R"( 3501 struct A { 3502 int Foo; 3503 }; 3504 3505 void target() { 3506 A A1; 3507 A A2; 3508 int Bar; 3509 A1.Foo = Bar; 3510 A2 = A1; 3511 // [[p]] 3512 } 3513 )"; 3514 runDataflow( 3515 Code, 3516 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3517 ASTContext &ASTCtx) { 3518 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3519 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3520 3521 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3522 ASSERT_THAT(FooDecl, NotNull()); 3523 3524 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3525 ASSERT_THAT(BarDecl, NotNull()); 3526 3527 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); 3528 ASSERT_THAT(A1Decl, NotNull()); 3529 3530 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); 3531 ASSERT_THAT(A2Decl, NotNull()); 3532 3533 const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3534 3535 const auto *A2Val = cast<RecordValue>(Env.getValue(*A2Decl)); 3536 EXPECT_EQ(getFieldValue(A2Val, *FooDecl, Env), BarVal); 3537 }); 3538 } 3539 3540 TEST(TransferTest, BooleanEquality) { 3541 std::string Code = R"( 3542 void target(bool Bar) { 3543 bool Foo = true; 3544 if (Bar == Foo) { 3545 (void)0; 3546 /*[[p-then]]*/ 3547 } else { 3548 (void)0; 3549 /*[[p-else]]*/ 3550 } 3551 } 3552 )"; 3553 runDataflow( 3554 Code, 3555 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3556 ASTContext &ASTCtx) { 3557 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else")); 3558 const Environment &EnvThen = 3559 getEnvironmentAtAnnotation(Results, "p-then"); 3560 const Environment &EnvElse = 3561 getEnvironmentAtAnnotation(Results, "p-else"); 3562 3563 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3564 ASSERT_THAT(BarDecl, NotNull()); 3565 3566 auto &BarValThen = getFormula(*BarDecl, EnvThen); 3567 EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen)); 3568 3569 auto &BarValElse = getFormula(*BarDecl, EnvElse); 3570 EXPECT_TRUE( 3571 EnvElse.flowConditionImplies(EnvElse.arena().makeNot(BarValElse))); 3572 }); 3573 } 3574 3575 TEST(TransferTest, BooleanInequality) { 3576 std::string Code = R"( 3577 void target(bool Bar) { 3578 bool Foo = true; 3579 if (Bar != Foo) { 3580 (void)0; 3581 /*[[p-then]]*/ 3582 } else { 3583 (void)0; 3584 /*[[p-else]]*/ 3585 } 3586 } 3587 )"; 3588 runDataflow( 3589 Code, 3590 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3591 ASTContext &ASTCtx) { 3592 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else")); 3593 const Environment &EnvThen = 3594 getEnvironmentAtAnnotation(Results, "p-then"); 3595 const Environment &EnvElse = 3596 getEnvironmentAtAnnotation(Results, "p-else"); 3597 3598 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3599 ASSERT_THAT(BarDecl, NotNull()); 3600 3601 auto &BarValThen = getFormula(*BarDecl, EnvThen); 3602 EXPECT_TRUE( 3603 EnvThen.flowConditionImplies(EnvThen.arena().makeNot(BarValThen))); 3604 3605 auto &BarValElse = getFormula(*BarDecl, EnvElse); 3606 EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse)); 3607 }); 3608 } 3609 3610 TEST(TransferTest, IntegerLiteralEquality) { 3611 std::string Code = R"( 3612 void target() { 3613 bool equal = (42 == 42); 3614 // [[p]] 3615 } 3616 )"; 3617 runDataflow( 3618 Code, 3619 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3620 ASTContext &ASTCtx) { 3621 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3622 3623 auto &Equal = 3624 getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula(); 3625 EXPECT_TRUE(Env.flowConditionImplies(Equal)); 3626 }); 3627 } 3628 3629 TEST(TransferTest, CorrelatedBranches) { 3630 std::string Code = R"( 3631 void target(bool B, bool C) { 3632 if (B) { 3633 return; 3634 } 3635 (void)0; 3636 /*[[p0]]*/ 3637 if (C) { 3638 B = true; 3639 /*[[p1]]*/ 3640 } 3641 if (B) { 3642 (void)0; 3643 /*[[p2]]*/ 3644 } 3645 } 3646 )"; 3647 runDataflow( 3648 Code, 3649 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3650 ASTContext &ASTCtx) { 3651 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2")); 3652 3653 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3654 ASSERT_THAT(CDecl, NotNull()); 3655 3656 { 3657 const Environment &Env = getEnvironmentAtAnnotation(Results, "p0"); 3658 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3659 ASSERT_THAT(BDecl, NotNull()); 3660 auto &BVal = getFormula(*BDecl, Env); 3661 3662 EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BVal))); 3663 } 3664 3665 { 3666 const Environment &Env = getEnvironmentAtAnnotation(Results, "p1"); 3667 auto &CVal = getFormula(*CDecl, Env); 3668 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3669 } 3670 3671 { 3672 const Environment &Env = getEnvironmentAtAnnotation(Results, "p2"); 3673 auto &CVal = getFormula(*CDecl, Env); 3674 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3675 } 3676 }); 3677 } 3678 3679 TEST(TransferTest, LoopWithAssignmentConverges) { 3680 std::string Code = R"( 3681 bool foo(); 3682 3683 void target() { 3684 do { 3685 bool Bar = foo(); 3686 if (Bar) break; 3687 (void)Bar; 3688 /*[[p]]*/ 3689 } while (true); 3690 } 3691 )"; 3692 // The key property that we are verifying is implicit in `runDataflow` -- 3693 // namely, that the analysis succeeds, rather than hitting the maximum number 3694 // of iterations. 3695 runDataflow( 3696 Code, 3697 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3698 ASTContext &ASTCtx) { 3699 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3700 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3701 3702 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3703 ASSERT_THAT(BarDecl, NotNull()); 3704 3705 auto &BarVal = getFormula(*BarDecl, Env); 3706 EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal))); 3707 }); 3708 } 3709 3710 TEST(TransferTest, LoopWithStagedAssignments) { 3711 std::string Code = R"( 3712 bool foo(); 3713 3714 void target() { 3715 bool Bar = false; 3716 bool Err = false; 3717 while (foo()) { 3718 if (Bar) 3719 Err = true; 3720 Bar = true; 3721 /*[[p]]*/ 3722 } 3723 } 3724 )"; 3725 runDataflow( 3726 Code, 3727 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3728 ASTContext &ASTCtx) { 3729 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3730 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3731 3732 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3733 ASSERT_THAT(BarDecl, NotNull()); 3734 const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err"); 3735 ASSERT_THAT(ErrDecl, NotNull()); 3736 3737 auto &BarVal = getFormula(*BarDecl, Env); 3738 auto &ErrVal = getFormula(*ErrDecl, Env); 3739 EXPECT_TRUE(Env.flowConditionImplies(BarVal)); 3740 // An unsound analysis, for example only evaluating the loop once, can 3741 // conclude that `Err` is false. So, we test that this conclusion is not 3742 // reached. 3743 EXPECT_FALSE( 3744 Env.flowConditionImplies(Env.arena().makeNot(ErrVal))); 3745 }); 3746 } 3747 3748 TEST(TransferTest, LoopWithReferenceAssignmentConverges) { 3749 std::string Code = R"( 3750 bool &foo(); 3751 3752 void target() { 3753 do { 3754 bool& Bar = foo(); 3755 if (Bar) break; 3756 (void)Bar; 3757 /*[[p]]*/ 3758 } while (true); 3759 } 3760 )"; 3761 // The key property that we are verifying is that the analysis succeeds, 3762 // rather than hitting the maximum number of iterations. 3763 runDataflow( 3764 Code, 3765 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3766 ASTContext &ASTCtx) { 3767 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3768 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3769 3770 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3771 ASSERT_THAT(BarDecl, NotNull()); 3772 3773 auto &BarVal = getFormula(*BarDecl, Env); 3774 EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal))); 3775 }); 3776 } 3777 3778 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) { 3779 std::string Code = R"( 3780 struct Lookup { 3781 int x; 3782 }; 3783 3784 void target(Lookup val, bool b) { 3785 const Lookup* l = nullptr; 3786 while (b) { 3787 l = &val; 3788 /*[[p-inner]]*/ 3789 } 3790 (void)0; 3791 /*[[p-outer]]*/ 3792 } 3793 )"; 3794 // The key property that we are verifying is implicit in `runDataflow` -- 3795 // namely, that the analysis succeeds, rather than hitting the maximum number 3796 // of iterations. 3797 runDataflow( 3798 Code, 3799 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3800 ASTContext &ASTCtx) { 3801 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer")); 3802 const Environment &InnerEnv = 3803 getEnvironmentAtAnnotation(Results, "p-inner"); 3804 const Environment &OuterEnv = 3805 getEnvironmentAtAnnotation(Results, "p-outer"); 3806 3807 const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val"); 3808 ASSERT_THAT(ValDecl, NotNull()); 3809 3810 const ValueDecl *LDecl = findValueDecl(ASTCtx, "l"); 3811 ASSERT_THAT(LDecl, NotNull()); 3812 3813 // Inner. 3814 auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl)); 3815 ASSERT_THAT(LVal, NotNull()); 3816 3817 EXPECT_EQ(&LVal->getPointeeLoc(), 3818 InnerEnv.getStorageLocation(*ValDecl)); 3819 3820 // Outer. 3821 LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl)); 3822 ASSERT_THAT(LVal, NotNull()); 3823 3824 // The loop body may not have been executed, so we should not conclude 3825 // that `l` points to `val`. 3826 EXPECT_NE(&LVal->getPointeeLoc(), 3827 OuterEnv.getStorageLocation(*ValDecl)); 3828 }); 3829 } 3830 3831 TEST(TransferTest, LoopDereferencingChangingPointerConverges) { 3832 std::string Code = R"cc( 3833 bool some_condition(); 3834 3835 void target(int i1, int i2) { 3836 int *p = &i1; 3837 while (true) { 3838 (void)*p; 3839 if (some_condition()) 3840 p = &i1; 3841 else 3842 p = &i2; 3843 } 3844 } 3845 )cc"; 3846 // FIXME: Implement pointer value widening to make analysis converge. 3847 ASSERT_THAT_ERROR( 3848 checkDataflowWithNoopAnalysis(Code), 3849 llvm::FailedWithMessage("maximum number of iterations reached")); 3850 } 3851 3852 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) { 3853 std::string Code = R"cc( 3854 struct Lookup { 3855 int x; 3856 }; 3857 3858 bool some_condition(); 3859 3860 void target(Lookup l1, Lookup l2) { 3861 Lookup *l = &l1; 3862 while (true) { 3863 (void)l->x; 3864 if (some_condition()) 3865 l = &l1; 3866 else 3867 l = &l2; 3868 } 3869 } 3870 )cc"; 3871 // FIXME: Implement pointer value widening to make analysis converge. 3872 ASSERT_THAT_ERROR( 3873 checkDataflowWithNoopAnalysis(Code), 3874 llvm::FailedWithMessage("maximum number of iterations reached")); 3875 } 3876 3877 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { 3878 std::string Code = R"( 3879 union Union { 3880 int A; 3881 float B; 3882 }; 3883 3884 void foo() { 3885 Union A; 3886 Union B; 3887 A = B; 3888 } 3889 )"; 3890 // This is a crash regression test when calling the transfer function on a 3891 // `CXXThisExpr` that refers to a union. 3892 runDataflow( 3893 Code, 3894 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &, 3895 ASTContext &) {}, 3896 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator="); 3897 } 3898 3899 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) { 3900 std::string Code = R"( 3901 struct A { 3902 int Foo; 3903 int Bar; 3904 }; 3905 3906 void target() { 3907 int Qux; 3908 A Baz; 3909 Baz.Foo = Qux; 3910 auto &FooRef = Baz.Foo; 3911 auto &BarRef = Baz.Bar; 3912 auto &[BoundFooRef, BoundBarRef] = Baz; 3913 // [[p]] 3914 } 3915 )"; 3916 runDataflow( 3917 Code, 3918 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3919 ASTContext &ASTCtx) { 3920 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3921 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3922 3923 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3924 ASSERT_THAT(FooRefDecl, NotNull()); 3925 3926 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3927 ASSERT_THAT(BarRefDecl, NotNull()); 3928 3929 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3930 ASSERT_THAT(QuxDecl, NotNull()); 3931 3932 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3933 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3934 3935 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3936 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3937 3938 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 3939 ASSERT_THAT(FooRefLoc, NotNull()); 3940 3941 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 3942 ASSERT_THAT(BarRefLoc, NotNull()); 3943 3944 const Value *QuxVal = Env.getValue(*QuxDecl); 3945 ASSERT_THAT(QuxVal, NotNull()); 3946 3947 const StorageLocation *BoundFooRefLoc = 3948 Env.getStorageLocation(*BoundFooRefDecl); 3949 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3950 3951 const StorageLocation *BoundBarRefLoc = 3952 Env.getStorageLocation(*BoundBarRefDecl); 3953 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3954 3955 EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal); 3956 }); 3957 } 3958 3959 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) { 3960 std::string Code = R"( 3961 struct A { 3962 int &Foo; 3963 int &Bar; 3964 }; 3965 3966 void target(A Baz) { 3967 int Qux; 3968 Baz.Foo = Qux; 3969 auto &FooRef = Baz.Foo; 3970 auto &BarRef = Baz.Bar; 3971 auto &[BoundFooRef, BoundBarRef] = Baz; 3972 // [[p]] 3973 } 3974 )"; 3975 runDataflow( 3976 Code, 3977 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3978 ASTContext &ASTCtx) { 3979 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3980 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3981 3982 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3983 ASSERT_THAT(FooRefDecl, NotNull()); 3984 3985 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3986 ASSERT_THAT(BarRefDecl, NotNull()); 3987 3988 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3989 ASSERT_THAT(QuxDecl, NotNull()); 3990 3991 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3992 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3993 3994 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3995 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3996 3997 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 3998 ASSERT_THAT(FooRefLoc, NotNull()); 3999 4000 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 4001 ASSERT_THAT(BarRefLoc, NotNull()); 4002 4003 const Value *QuxVal = Env.getValue(*QuxDecl); 4004 ASSERT_THAT(QuxVal, NotNull()); 4005 4006 const StorageLocation *BoundFooRefLoc = 4007 Env.getStorageLocation(*BoundFooRefDecl); 4008 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 4009 4010 const StorageLocation *BoundBarRefLoc = 4011 Env.getStorageLocation(*BoundBarRefDecl); 4012 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 4013 4014 EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal); 4015 }); 4016 } 4017 4018 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) { 4019 std::string Code = R"( 4020 struct A { 4021 int Foo; 4022 int Bar; 4023 }; 4024 4025 void target() { 4026 int Qux; 4027 A Baz; 4028 Baz.Foo = Qux; 4029 auto &FooRef = Baz.Foo; 4030 auto &BarRef = Baz.Bar; 4031 auto [BoundFoo, BoundBar] = Baz; 4032 // [[p]] 4033 } 4034 )"; 4035 runDataflow( 4036 Code, 4037 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4038 ASTContext &ASTCtx) { 4039 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4040 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4041 4042 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 4043 ASSERT_THAT(FooRefDecl, NotNull()); 4044 4045 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 4046 ASSERT_THAT(BarRefDecl, NotNull()); 4047 4048 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 4049 ASSERT_THAT(BoundFooDecl, NotNull()); 4050 4051 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 4052 ASSERT_THAT(BoundBarDecl, NotNull()); 4053 4054 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 4055 ASSERT_THAT(QuxDecl, NotNull()); 4056 4057 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 4058 ASSERT_THAT(FooRefLoc, NotNull()); 4059 4060 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 4061 ASSERT_THAT(BarRefLoc, NotNull()); 4062 4063 const Value *QuxVal = Env.getValue(*QuxDecl); 4064 ASSERT_THAT(QuxVal, NotNull()); 4065 4066 const StorageLocation *BoundFooLoc = 4067 Env.getStorageLocation(*BoundFooDecl); 4068 EXPECT_NE(BoundFooLoc, FooRefLoc); 4069 4070 const StorageLocation *BoundBarLoc = 4071 Env.getStorageLocation(*BoundBarDecl); 4072 EXPECT_NE(BoundBarLoc, BarRefLoc); 4073 4074 EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal); 4075 }); 4076 } 4077 4078 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) { 4079 std::string Code = R"( 4080 namespace std { 4081 using size_t = int; 4082 template <class> struct tuple_size; 4083 template <std::size_t, class> struct tuple_element; 4084 template <class...> class tuple; 4085 4086 namespace { 4087 template <class T, T v> 4088 struct size_helper { static const T value = v; }; 4089 } // namespace 4090 4091 template <class... T> 4092 struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {}; 4093 4094 template <std::size_t I, class... T> 4095 struct tuple_element<I, tuple<T...>> { 4096 using type = __type_pack_element<I, T...>; 4097 }; 4098 4099 template <class...> class tuple {}; 4100 4101 template <std::size_t I, class... T> 4102 typename tuple_element<I, tuple<T...>>::type get(tuple<T...>); 4103 } // namespace std 4104 4105 std::tuple<bool, int> makeTuple(); 4106 4107 void target(bool B) { 4108 auto [BoundFoo, BoundBar] = makeTuple(); 4109 bool Baz; 4110 // Include if-then-else to test interaction of `BindingDecl` with join. 4111 if (B) { 4112 Baz = BoundFoo; 4113 (void)BoundBar; 4114 // [[p1]] 4115 } else { 4116 Baz = BoundFoo; 4117 } 4118 (void)0; 4119 // [[p2]] 4120 } 4121 )"; 4122 runDataflow( 4123 Code, 4124 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4125 ASTContext &ASTCtx) { 4126 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 4127 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 4128 4129 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 4130 ASSERT_THAT(BoundFooDecl, NotNull()); 4131 4132 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 4133 ASSERT_THAT(BoundBarDecl, NotNull()); 4134 4135 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4136 ASSERT_THAT(BazDecl, NotNull()); 4137 4138 // BindingDecls always map to references -- either lvalue or rvalue, so 4139 // we still need to skip here. 4140 const Value *BoundFooValue = Env1.getValue(*BoundFooDecl); 4141 ASSERT_THAT(BoundFooValue, NotNull()); 4142 EXPECT_TRUE(isa<BoolValue>(BoundFooValue)); 4143 4144 const Value *BoundBarValue = Env1.getValue(*BoundBarDecl); 4145 ASSERT_THAT(BoundBarValue, NotNull()); 4146 EXPECT_TRUE(isa<IntegerValue>(BoundBarValue)); 4147 4148 // Test that a `DeclRefExpr` to a `BindingDecl` works as expected. 4149 EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue); 4150 4151 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 4152 4153 // Test that `BoundFooDecl` retains the value we expect, after the join. 4154 BoundFooValue = Env2.getValue(*BoundFooDecl); 4155 EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue); 4156 }); 4157 } 4158 4159 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) { 4160 std::string Code = R"( 4161 namespace std { 4162 using size_t = int; 4163 template <class> struct tuple_size; 4164 template <std::size_t, class> struct tuple_element; 4165 template <class...> class tuple; 4166 4167 namespace { 4168 template <class T, T v> 4169 struct size_helper { static const T value = v; }; 4170 } // namespace 4171 4172 template <class... T> 4173 struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {}; 4174 4175 template <std::size_t I, class... T> 4176 struct tuple_element<I, tuple<T...>> { 4177 using type = __type_pack_element<I, T...>; 4178 }; 4179 4180 template <class...> class tuple {}; 4181 4182 template <std::size_t I, class... T> 4183 typename tuple_element<I, tuple<T...>>::type get(tuple<T...>); 4184 } // namespace std 4185 4186 std::tuple<bool, int> &getTuple(); 4187 4188 void target(bool B) { 4189 auto &[BoundFoo, BoundBar] = getTuple(); 4190 bool Baz; 4191 // Include if-then-else to test interaction of `BindingDecl` with join. 4192 if (B) { 4193 Baz = BoundFoo; 4194 (void)BoundBar; 4195 // [[p1]] 4196 } else { 4197 Baz = BoundFoo; 4198 } 4199 (void)0; 4200 // [[p2]] 4201 } 4202 )"; 4203 runDataflow( 4204 Code, 4205 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4206 ASTContext &ASTCtx) { 4207 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 4208 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 4209 4210 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 4211 ASSERT_THAT(BoundFooDecl, NotNull()); 4212 4213 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 4214 ASSERT_THAT(BoundBarDecl, NotNull()); 4215 4216 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4217 ASSERT_THAT(BazDecl, NotNull()); 4218 4219 const Value *BoundFooValue = Env1.getValue(*BoundFooDecl); 4220 ASSERT_THAT(BoundFooValue, NotNull()); 4221 EXPECT_TRUE(isa<BoolValue>(BoundFooValue)); 4222 4223 const Value *BoundBarValue = Env1.getValue(*BoundBarDecl); 4224 ASSERT_THAT(BoundBarValue, NotNull()); 4225 EXPECT_TRUE(isa<IntegerValue>(BoundBarValue)); 4226 4227 // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type) 4228 // works as expected. We don't test aliasing properties of the 4229 // reference, because we don't model `std::get` and so have no way to 4230 // equate separate references into the tuple. 4231 EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue); 4232 4233 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 4234 4235 // Test that `BoundFooDecl` retains the value we expect, after the join. 4236 BoundFooValue = Env2.getValue(*BoundFooDecl); 4237 EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue); 4238 }); 4239 } 4240 4241 TEST(TransferTest, BinaryOperatorComma) { 4242 std::string Code = R"( 4243 void target(int Foo, int Bar) { 4244 int &Baz = (Foo, Bar); 4245 // [[p]] 4246 } 4247 )"; 4248 runDataflow( 4249 Code, 4250 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4251 ASTContext &ASTCtx) { 4252 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4253 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4254 4255 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4256 ASSERT_THAT(BarDecl, NotNull()); 4257 4258 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4259 ASSERT_THAT(BazDecl, NotNull()); 4260 4261 const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl); 4262 ASSERT_THAT(BarLoc, NotNull()); 4263 4264 const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl); 4265 EXPECT_EQ(BazLoc, BarLoc); 4266 }); 4267 } 4268 4269 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) { 4270 std::string Code = R"( 4271 void target(bool Foo) { 4272 if (Foo) { 4273 (void)0; 4274 // [[if_then]] 4275 } else { 4276 (void)0; 4277 // [[if_else]] 4278 } 4279 } 4280 )"; 4281 runDataflow( 4282 Code, 4283 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4284 ASTContext &ASTCtx) { 4285 ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else")); 4286 const Environment &ThenEnv = 4287 getEnvironmentAtAnnotation(Results, "if_then"); 4288 const Environment &ElseEnv = 4289 getEnvironmentAtAnnotation(Results, "if_else"); 4290 4291 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4292 ASSERT_THAT(FooDecl, NotNull()); 4293 4294 auto &ThenFooVal= getFormula(*FooDecl, ThenEnv); 4295 EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal)); 4296 4297 auto &ElseFooVal = getFormula(*FooDecl, ElseEnv); 4298 EXPECT_TRUE( 4299 ElseEnv.flowConditionImplies(ElseEnv.arena().makeNot(ElseFooVal))); 4300 }); 4301 } 4302 4303 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) { 4304 std::string Code = R"( 4305 void target(bool Foo) { 4306 while (Foo) { 4307 (void)0; 4308 // [[loop_body]] 4309 } 4310 (void)0; 4311 // [[after_loop]] 4312 } 4313 )"; 4314 runDataflow( 4315 Code, 4316 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4317 ASTContext &ASTCtx) { 4318 ASSERT_THAT(Results.keys(), 4319 UnorderedElementsAre("loop_body", "after_loop")); 4320 const Environment &LoopBodyEnv = 4321 getEnvironmentAtAnnotation(Results, "loop_body"); 4322 const Environment &AfterLoopEnv = 4323 getEnvironmentAtAnnotation(Results, "after_loop"); 4324 4325 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4326 ASSERT_THAT(FooDecl, NotNull()); 4327 4328 auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv); 4329 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4330 4331 auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv); 4332 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4333 AfterLoopEnv.arena().makeNot(AfterLoopFooVal))); 4334 }); 4335 } 4336 4337 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) { 4338 std::string Code = R"( 4339 void target(bool Foo) { 4340 bool Bar = true; 4341 do { 4342 (void)0; 4343 // [[loop_body]] 4344 Bar = false; 4345 } while (Foo); 4346 (void)0; 4347 // [[after_loop]] 4348 } 4349 )"; 4350 runDataflow( 4351 Code, 4352 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4353 ASTContext &ASTCtx) { 4354 ASSERT_THAT(Results.keys(), 4355 UnorderedElementsAre("loop_body", "after_loop")); 4356 const Environment &LoopBodyEnv = 4357 getEnvironmentAtAnnotation(Results, "loop_body"); 4358 const Environment &AfterLoopEnv = 4359 getEnvironmentAtAnnotation(Results, "after_loop"); 4360 auto &A = AfterLoopEnv.arena(); 4361 4362 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4363 ASSERT_THAT(FooDecl, NotNull()); 4364 4365 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4366 ASSERT_THAT(BarDecl, NotNull()); 4367 4368 auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv); 4369 auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv); 4370 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies( 4371 A.makeOr(LoopBodyBarVal, LoopBodyFooVal))); 4372 4373 auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv); 4374 auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv); 4375 EXPECT_TRUE( 4376 AfterLoopEnv.flowConditionImplies(A.makeNot(AfterLoopFooVal))); 4377 EXPECT_TRUE( 4378 AfterLoopEnv.flowConditionImplies(A.makeNot(AfterLoopBarVal))); 4379 }); 4380 } 4381 4382 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) { 4383 std::string Code = R"( 4384 void target(bool Foo) { 4385 for (; Foo;) { 4386 (void)0; 4387 // [[loop_body]] 4388 } 4389 (void)0; 4390 // [[after_loop]] 4391 } 4392 )"; 4393 runDataflow( 4394 Code, 4395 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4396 ASTContext &ASTCtx) { 4397 ASSERT_THAT(Results.keys(), 4398 UnorderedElementsAre("loop_body", "after_loop")); 4399 const Environment &LoopBodyEnv = 4400 getEnvironmentAtAnnotation(Results, "loop_body"); 4401 const Environment &AfterLoopEnv = 4402 getEnvironmentAtAnnotation(Results, "after_loop"); 4403 4404 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4405 ASSERT_THAT(FooDecl, NotNull()); 4406 4407 auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv); 4408 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4409 4410 auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv); 4411 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4412 AfterLoopEnv.arena().makeNot(AfterLoopFooVal))); 4413 }); 4414 } 4415 4416 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) { 4417 std::string Code = R"( 4418 void target(bool Foo) { 4419 for (;;) { 4420 (void)0; 4421 // [[loop_body]] 4422 } 4423 } 4424 )"; 4425 runDataflow( 4426 Code, 4427 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4428 ASTContext &ASTCtx) { 4429 ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body")); 4430 const Environment &LoopBodyEnv = 4431 getEnvironmentAtAnnotation(Results, "loop_body"); 4432 4433 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4434 ASSERT_THAT(FooDecl, NotNull()); 4435 4436 auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv); 4437 EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4438 }); 4439 } 4440 4441 TEST(TransferTest, ContextSensitiveOptionDisabled) { 4442 std::string Code = R"( 4443 bool GiveBool(); 4444 void SetBool(bool &Var) { Var = true; } 4445 4446 void target() { 4447 bool Foo = GiveBool(); 4448 SetBool(Foo); 4449 // [[p]] 4450 } 4451 )"; 4452 runDataflow( 4453 Code, 4454 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4455 ASTContext &ASTCtx) { 4456 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4457 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4458 4459 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4460 ASSERT_THAT(FooDecl, NotNull()); 4461 4462 auto &FooVal = getFormula(*FooDecl, Env); 4463 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4464 EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 4465 }, 4466 {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}}); 4467 } 4468 4469 TEST(TransferTest, ContextSensitiveReturnReference) { 4470 std::string Code = R"( 4471 class S {}; 4472 S& target(bool b, S &s) { 4473 return s; 4474 // [[p]] 4475 } 4476 )"; 4477 runDataflow( 4478 Code, 4479 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4480 ASTContext &ASTCtx) { 4481 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4482 4483 const ValueDecl *SDecl = findValueDecl(ASTCtx, "s"); 4484 ASSERT_THAT(SDecl, NotNull()); 4485 4486 auto *SLoc = Env.getStorageLocation(*SDecl); 4487 ASSERT_THAT(SLoc, NotNull()); 4488 4489 ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc)); 4490 }, 4491 {BuiltinOptions{ContextSensitiveOptions{}}}); 4492 } 4493 4494 // This test is a regression test, based on a real crash. 4495 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) { 4496 std::string Code = R"( 4497 class S {}; 4498 S& target(bool b, S &s) { 4499 return b ? s : s; 4500 // [[p]] 4501 } 4502 )"; 4503 runDataflow( 4504 Code, 4505 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4506 ASTContext &ASTCtx) { 4507 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4508 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4509 4510 const ValueDecl *SDecl = findValueDecl(ASTCtx, "s"); 4511 ASSERT_THAT(SDecl, NotNull()); 4512 4513 auto *SLoc = Env.getStorageLocation(*SDecl); 4514 ASSERT_THAT(SLoc, NotNull()); 4515 EXPECT_THAT(Env.getValue(*SLoc), NotNull()); 4516 4517 auto *Loc = Env.getReturnStorageLocation(); 4518 ASSERT_THAT(Loc, NotNull()); 4519 EXPECT_THAT(Env.getValue(*Loc), NotNull()); 4520 4521 // TODO: We would really like to make this stronger assertion, but that 4522 // doesn't work because we don't propagate values correctly through 4523 // the conditional operator yet. 4524 // ASSERT_THAT(Loc, Eq(SLoc)); 4525 }, 4526 {BuiltinOptions{ContextSensitiveOptions{}}}); 4527 } 4528 4529 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) { 4530 std::string Code = R"( 4531 class S {}; 4532 S &callee(bool b, S &s1_parm, S &s2_parm) { 4533 if (b) 4534 return s1_parm; 4535 else 4536 return s2_parm; 4537 } 4538 void target(bool b) { 4539 S s1; 4540 S s2; 4541 S &return_s1 = s1; 4542 S &return_s2 = s2; 4543 S &return_dont_know = callee(b, s1, s2); 4544 // [[p]] 4545 } 4546 )"; 4547 runDataflow( 4548 Code, 4549 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4550 ASTContext &ASTCtx) { 4551 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4552 4553 const ValueDecl *S1 = findValueDecl(ASTCtx, "s1"); 4554 ASSERT_THAT(S1, NotNull()); 4555 const ValueDecl *S2 = findValueDecl(ASTCtx, "s2"); 4556 ASSERT_THAT(S2, NotNull()); 4557 const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1"); 4558 ASSERT_THAT(ReturnS1, NotNull()); 4559 const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2"); 4560 ASSERT_THAT(ReturnS2, NotNull()); 4561 const ValueDecl *ReturnDontKnow = 4562 findValueDecl(ASTCtx, "return_dont_know"); 4563 ASSERT_THAT(ReturnDontKnow, NotNull()); 4564 4565 StorageLocation *S1Loc = Env.getStorageLocation(*S1); 4566 StorageLocation *S2Loc = Env.getStorageLocation(*S2); 4567 4568 EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc)); 4569 EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc)); 4570 4571 // In the case where we don't have a consistent storage location for 4572 // the return value, the framework creates a new storage location, which 4573 // should be different from the storage locations of `s1` and `s2`. 4574 EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc)); 4575 EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc)); 4576 }, 4577 {BuiltinOptions{ContextSensitiveOptions{}}}); 4578 } 4579 4580 TEST(TransferTest, ContextSensitiveDepthZero) { 4581 std::string Code = R"( 4582 bool GiveBool(); 4583 void SetBool(bool &Var) { Var = true; } 4584 4585 void target() { 4586 bool Foo = GiveBool(); 4587 SetBool(Foo); 4588 // [[p]] 4589 } 4590 )"; 4591 runDataflow( 4592 Code, 4593 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4594 ASTContext &ASTCtx) { 4595 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4596 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4597 4598 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4599 ASSERT_THAT(FooDecl, NotNull()); 4600 4601 auto &FooVal = getFormula(*FooDecl, Env); 4602 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4603 EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 4604 }, 4605 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}}); 4606 } 4607 4608 TEST(TransferTest, ContextSensitiveSetTrue) { 4609 std::string Code = R"( 4610 bool GiveBool(); 4611 void SetBool(bool &Var) { Var = true; } 4612 4613 void target() { 4614 bool Foo = GiveBool(); 4615 SetBool(Foo); 4616 // [[p]] 4617 } 4618 )"; 4619 runDataflow( 4620 Code, 4621 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4622 ASTContext &ASTCtx) { 4623 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4624 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4625 4626 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4627 ASSERT_THAT(FooDecl, NotNull()); 4628 4629 auto &FooVal = getFormula(*FooDecl, Env); 4630 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4631 }, 4632 {BuiltinOptions{ContextSensitiveOptions{}}}); 4633 } 4634 4635 TEST(TransferTest, ContextSensitiveSetFalse) { 4636 std::string Code = R"( 4637 bool GiveBool(); 4638 void SetBool(bool &Var) { Var = false; } 4639 4640 void target() { 4641 bool Foo = GiveBool(); 4642 SetBool(Foo); 4643 // [[p]] 4644 } 4645 )"; 4646 runDataflow( 4647 Code, 4648 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4649 ASTContext &ASTCtx) { 4650 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4651 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4652 4653 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4654 ASSERT_THAT(FooDecl, NotNull()); 4655 4656 auto &FooVal = getFormula(*FooDecl, Env); 4657 EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 4658 }, 4659 {BuiltinOptions{ContextSensitiveOptions{}}}); 4660 } 4661 4662 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) { 4663 std::string Code = R"( 4664 bool GiveBool(); 4665 void SetBool(bool &Var, bool Val) { Var = Val; } 4666 4667 void target() { 4668 bool Foo = GiveBool(); 4669 bool Bar = GiveBool(); 4670 SetBool(Foo, true); 4671 SetBool(Bar, false); 4672 // [[p]] 4673 } 4674 )"; 4675 runDataflow( 4676 Code, 4677 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4678 ASTContext &ASTCtx) { 4679 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4680 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4681 auto &A = Env.arena(); 4682 4683 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4684 ASSERT_THAT(FooDecl, NotNull()); 4685 4686 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4687 ASSERT_THAT(BarDecl, NotNull()); 4688 4689 auto &FooVal = getFormula(*FooDecl, Env); 4690 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4691 EXPECT_FALSE(Env.flowConditionImplies(A.makeNot(FooVal))); 4692 4693 auto &BarVal = getFormula(*BarDecl, Env); 4694 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4695 EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(BarVal))); 4696 }, 4697 {BuiltinOptions{ContextSensitiveOptions{}}}); 4698 } 4699 4700 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) { 4701 std::string Code = R"( 4702 bool GiveBool(); 4703 void SetBool1(bool &Var) { Var = true; } 4704 void SetBool2(bool &Var) { SetBool1(Var); } 4705 4706 void target() { 4707 bool Foo = GiveBool(); 4708 SetBool2(Foo); 4709 // [[p]] 4710 } 4711 )"; 4712 runDataflow( 4713 Code, 4714 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4715 ASTContext &ASTCtx) { 4716 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4717 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4718 4719 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4720 ASSERT_THAT(FooDecl, NotNull()); 4721 4722 auto &FooVal = getFormula(*FooDecl, Env); 4723 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4724 EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 4725 }, 4726 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}}); 4727 } 4728 4729 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) { 4730 std::string Code = R"( 4731 bool GiveBool(); 4732 void SetBool1(bool &Var) { Var = true; } 4733 void SetBool2(bool &Var) { SetBool1(Var); } 4734 4735 void target() { 4736 bool Foo = GiveBool(); 4737 SetBool2(Foo); 4738 // [[p]] 4739 } 4740 )"; 4741 runDataflow( 4742 Code, 4743 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4744 ASTContext &ASTCtx) { 4745 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4746 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4747 4748 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4749 ASSERT_THAT(FooDecl, NotNull()); 4750 4751 auto &FooVal = getFormula(*FooDecl, Env); 4752 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4753 }, 4754 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}}); 4755 } 4756 4757 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) { 4758 std::string Code = R"( 4759 bool GiveBool(); 4760 void SetBool1(bool &Var) { Var = true; } 4761 void SetBool2(bool &Var) { SetBool1(Var); } 4762 void SetBool3(bool &Var) { SetBool2(Var); } 4763 4764 void target() { 4765 bool Foo = GiveBool(); 4766 SetBool3(Foo); 4767 // [[p]] 4768 } 4769 )"; 4770 runDataflow( 4771 Code, 4772 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4773 ASTContext &ASTCtx) { 4774 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4775 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4776 4777 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4778 ASSERT_THAT(FooDecl, NotNull()); 4779 4780 auto &FooVal = getFormula(*FooDecl, Env); 4781 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4782 EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 4783 }, 4784 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}}); 4785 } 4786 4787 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) { 4788 std::string Code = R"( 4789 bool GiveBool(); 4790 void SetBool1(bool &Var) { Var = true; } 4791 void SetBool2(bool &Var) { SetBool1(Var); } 4792 void SetBool3(bool &Var) { SetBool2(Var); } 4793 4794 void target() { 4795 bool Foo = GiveBool(); 4796 SetBool3(Foo); 4797 // [[p]] 4798 } 4799 )"; 4800 runDataflow( 4801 Code, 4802 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4803 ASTContext &ASTCtx) { 4804 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4805 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4806 4807 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4808 ASSERT_THAT(FooDecl, NotNull()); 4809 4810 auto &FooVal = getFormula(*FooDecl, Env); 4811 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4812 }, 4813 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}}); 4814 } 4815 4816 TEST(TransferTest, ContextSensitiveMutualRecursion) { 4817 std::string Code = R"( 4818 bool Pong(bool X, bool Y); 4819 4820 bool Ping(bool X, bool Y) { 4821 if (X) { 4822 return Y; 4823 } else { 4824 return Pong(!X, Y); 4825 } 4826 } 4827 4828 bool Pong(bool X, bool Y) { 4829 if (Y) { 4830 return X; 4831 } else { 4832 return Ping(X, !Y); 4833 } 4834 } 4835 4836 void target() { 4837 bool Foo = Ping(false, false); 4838 // [[p]] 4839 } 4840 )"; 4841 runDataflow( 4842 Code, 4843 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4844 ASTContext &ASTCtx) { 4845 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4846 // The analysis doesn't crash... 4847 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4848 4849 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4850 ASSERT_THAT(FooDecl, NotNull()); 4851 4852 auto &FooVal = getFormula(*FooDecl, Env); 4853 // ... but it also can't prove anything here. 4854 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4855 EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 4856 }, 4857 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}}); 4858 } 4859 4860 TEST(TransferTest, ContextSensitiveSetMultipleLines) { 4861 std::string Code = R"( 4862 void SetBools(bool &Var1, bool &Var2) { 4863 Var1 = true; 4864 Var2 = false; 4865 } 4866 4867 void target() { 4868 bool Foo = false; 4869 bool Bar = true; 4870 SetBools(Foo, Bar); 4871 // [[p]] 4872 } 4873 )"; 4874 runDataflow( 4875 Code, 4876 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4877 ASTContext &ASTCtx) { 4878 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4879 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4880 4881 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4882 ASSERT_THAT(FooDecl, NotNull()); 4883 4884 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4885 ASSERT_THAT(BarDecl, NotNull()); 4886 4887 auto &FooVal = getFormula(*FooDecl, Env); 4888 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4889 EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 4890 4891 auto &BarVal = getFormula(*BarDecl, Env); 4892 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4893 EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal))); 4894 }, 4895 {BuiltinOptions{ContextSensitiveOptions{}}}); 4896 } 4897 4898 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) { 4899 std::string Code = R"( 4900 void IfCond(bool Cond, bool &Then, bool &Else) { 4901 if (Cond) { 4902 Then = true; 4903 } else { 4904 Else = true; 4905 } 4906 } 4907 4908 void target() { 4909 bool Foo = false; 4910 bool Bar = false; 4911 bool Baz = false; 4912 IfCond(Foo, Bar, Baz); 4913 // [[p]] 4914 } 4915 )"; 4916 runDataflow( 4917 Code, 4918 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4919 ASTContext &ASTCtx) { 4920 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4921 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4922 4923 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4924 ASSERT_THAT(BarDecl, NotNull()); 4925 4926 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4927 ASSERT_THAT(BazDecl, NotNull()); 4928 4929 auto &BarVal = getFormula(*BarDecl, Env); 4930 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4931 EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal))); 4932 4933 auto &BazVal = getFormula(*BazDecl, Env); 4934 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 4935 EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(BazVal))); 4936 }, 4937 {BuiltinOptions{ContextSensitiveOptions{}}}); 4938 } 4939 4940 TEST(TransferTest, ContextSensitiveReturnVoid) { 4941 std::string Code = R"( 4942 void Noop() { return; } 4943 4944 void target() { 4945 Noop(); 4946 // [[p]] 4947 } 4948 )"; 4949 runDataflow( 4950 Code, 4951 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4952 ASTContext &ASTCtx) { 4953 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4954 // This just tests that the analysis doesn't crash. 4955 }, 4956 {BuiltinOptions{ContextSensitiveOptions{}}}); 4957 } 4958 4959 TEST(TransferTest, ContextSensitiveReturnTrue) { 4960 std::string Code = R"( 4961 bool GiveBool() { return true; } 4962 4963 void target() { 4964 bool Foo = GiveBool(); 4965 // [[p]] 4966 } 4967 )"; 4968 runDataflow( 4969 Code, 4970 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4971 ASTContext &ASTCtx) { 4972 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4973 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4974 4975 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4976 ASSERT_THAT(FooDecl, NotNull()); 4977 4978 auto &FooVal = getFormula(*FooDecl, Env); 4979 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4980 }, 4981 {BuiltinOptions{ContextSensitiveOptions{}}}); 4982 } 4983 4984 TEST(TransferTest, ContextSensitiveReturnFalse) { 4985 std::string Code = R"( 4986 bool GiveBool() { return false; } 4987 4988 void target() { 4989 bool Foo = GiveBool(); 4990 // [[p]] 4991 } 4992 )"; 4993 runDataflow( 4994 Code, 4995 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4996 ASTContext &ASTCtx) { 4997 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4998 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4999 5000 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5001 ASSERT_THAT(FooDecl, NotNull()); 5002 5003 auto &FooVal = getFormula(*FooDecl, Env); 5004 EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(FooVal))); 5005 }, 5006 {BuiltinOptions{ContextSensitiveOptions{}}}); 5007 } 5008 5009 TEST(TransferTest, ContextSensitiveReturnArg) { 5010 std::string Code = R"( 5011 bool GiveBool(); 5012 bool GiveBack(bool Arg) { return Arg; } 5013 5014 void target() { 5015 bool Foo = GiveBool(); 5016 bool Bar = GiveBack(Foo); 5017 bool Baz = Foo == Bar; 5018 // [[p]] 5019 } 5020 )"; 5021 runDataflow( 5022 Code, 5023 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5024 ASTContext &ASTCtx) { 5025 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5026 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5027 5028 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 5029 ASSERT_THAT(BazDecl, NotNull()); 5030 5031 auto &BazVal = getFormula(*BazDecl, Env); 5032 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 5033 }, 5034 {BuiltinOptions{ContextSensitiveOptions{}}}); 5035 } 5036 5037 TEST(TransferTest, ContextSensitiveReturnInt) { 5038 std::string Code = R"( 5039 int identity(int x) { return x; } 5040 5041 void target() { 5042 int y = identity(42); 5043 // [[p]] 5044 } 5045 )"; 5046 runDataflow( 5047 Code, 5048 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5049 ASTContext &ASTCtx) { 5050 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5051 // This just tests that the analysis doesn't crash. 5052 }, 5053 {BuiltinOptions{ContextSensitiveOptions{}}}); 5054 } 5055 5056 TEST(TransferTest, ContextSensitiveMethodLiteral) { 5057 std::string Code = R"( 5058 class MyClass { 5059 public: 5060 bool giveBool() { return true; } 5061 }; 5062 5063 void target() { 5064 MyClass MyObj; 5065 bool Foo = MyObj.giveBool(); 5066 // [[p]] 5067 } 5068 )"; 5069 runDataflow( 5070 Code, 5071 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5072 ASTContext &ASTCtx) { 5073 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5074 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5075 5076 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5077 ASSERT_THAT(FooDecl, NotNull()); 5078 5079 auto &FooVal = getFormula(*FooDecl, Env); 5080 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5081 }, 5082 {BuiltinOptions{ContextSensitiveOptions{}}}); 5083 } 5084 5085 TEST(TransferTest, ContextSensitiveMethodGetter) { 5086 std::string Code = R"( 5087 class MyClass { 5088 public: 5089 bool getField() { return Field; } 5090 5091 bool Field; 5092 }; 5093 5094 void target() { 5095 MyClass MyObj; 5096 MyObj.Field = true; 5097 bool Foo = MyObj.getField(); 5098 // [[p]] 5099 } 5100 )"; 5101 runDataflow( 5102 Code, 5103 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5104 ASTContext &ASTCtx) { 5105 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5106 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5107 5108 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5109 ASSERT_THAT(FooDecl, NotNull()); 5110 5111 auto &FooVal = getFormula(*FooDecl, Env); 5112 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5113 }, 5114 {BuiltinOptions{ContextSensitiveOptions{}}}); 5115 } 5116 5117 TEST(TransferTest, ContextSensitiveMethodSetter) { 5118 std::string Code = R"( 5119 class MyClass { 5120 public: 5121 void setField(bool Val) { Field = Val; } 5122 5123 bool Field; 5124 }; 5125 5126 void target() { 5127 MyClass MyObj; 5128 MyObj.setField(true); 5129 bool Foo = MyObj.Field; 5130 // [[p]] 5131 } 5132 )"; 5133 runDataflow( 5134 Code, 5135 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5136 ASTContext &ASTCtx) { 5137 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5138 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5139 5140 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5141 ASSERT_THAT(FooDecl, NotNull()); 5142 5143 auto &FooVal = getFormula(*FooDecl, Env); 5144 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5145 }, 5146 {BuiltinOptions{ContextSensitiveOptions{}}}); 5147 } 5148 5149 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) { 5150 std::string Code = R"( 5151 class MyClass { 5152 public: 5153 bool getField() { return Field; } 5154 void setField(bool Val) { Field = Val; } 5155 5156 private: 5157 bool Field; 5158 }; 5159 5160 void target() { 5161 MyClass MyObj; 5162 MyObj.setField(true); 5163 bool Foo = MyObj.getField(); 5164 // [[p]] 5165 } 5166 )"; 5167 runDataflow( 5168 Code, 5169 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5170 ASTContext &ASTCtx) { 5171 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5172 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5173 5174 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5175 ASSERT_THAT(FooDecl, NotNull()); 5176 5177 auto &FooVal = getFormula(*FooDecl, Env); 5178 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5179 }, 5180 {BuiltinOptions{ContextSensitiveOptions{}}}); 5181 } 5182 5183 5184 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) { 5185 std::string Code = R"( 5186 class MyClass { 5187 public: 5188 void Inner() { MyField = true; } 5189 void Outer() { Inner(); } 5190 5191 bool MyField; 5192 }; 5193 5194 void target() { 5195 MyClass MyObj; 5196 MyObj.Outer(); 5197 bool Foo = MyObj.MyField; 5198 // [[p]] 5199 } 5200 )"; 5201 runDataflow( 5202 Code, 5203 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5204 ASTContext &ASTCtx) { 5205 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5206 ; 5207 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5208 5209 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5210 ASSERT_THAT(FooDecl, NotNull()); 5211 5212 auto &FooVal = getFormula(*FooDecl, Env); 5213 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5214 }, 5215 {BuiltinOptions{ContextSensitiveOptions{}}}); 5216 } 5217 5218 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) { 5219 std::string Code = R"( 5220 class MyClass { 5221 public: 5222 bool Inner() { return MyField; } 5223 bool Outer() { return Inner(); } 5224 5225 bool MyField; 5226 }; 5227 5228 void target() { 5229 MyClass MyObj; 5230 MyObj.MyField = true; 5231 bool Foo = MyObj.Outer(); 5232 // [[p]] 5233 } 5234 )"; 5235 runDataflow( 5236 Code, 5237 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5238 ASTContext &ASTCtx) { 5239 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5240 ; 5241 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5242 5243 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5244 ASSERT_THAT(FooDecl, NotNull()); 5245 5246 auto &FooVal = getFormula(*FooDecl, Env); 5247 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5248 }, 5249 {BuiltinOptions{ContextSensitiveOptions{}}}); 5250 } 5251 5252 TEST(TransferTest, ContextSensitiveConstructorBody) { 5253 std::string Code = R"( 5254 class MyClass { 5255 public: 5256 MyClass() { MyField = true; } 5257 5258 bool MyField; 5259 }; 5260 5261 void target() { 5262 MyClass MyObj; 5263 bool Foo = MyObj.MyField; 5264 // [[p]] 5265 } 5266 )"; 5267 runDataflow( 5268 Code, 5269 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5270 ASTContext &ASTCtx) { 5271 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5272 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5273 5274 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5275 ASSERT_THAT(FooDecl, NotNull()); 5276 5277 auto &FooVal = getFormula(*FooDecl, Env); 5278 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5279 }, 5280 {BuiltinOptions{ContextSensitiveOptions{}}}); 5281 } 5282 5283 TEST(TransferTest, ContextSensitiveConstructorInitializer) { 5284 std::string Code = R"( 5285 class MyClass { 5286 public: 5287 MyClass() : MyField(true) {} 5288 5289 bool MyField; 5290 }; 5291 5292 void target() { 5293 MyClass MyObj; 5294 bool Foo = MyObj.MyField; 5295 // [[p]] 5296 } 5297 )"; 5298 runDataflow( 5299 Code, 5300 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5301 ASTContext &ASTCtx) { 5302 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5303 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5304 5305 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5306 ASSERT_THAT(FooDecl, NotNull()); 5307 5308 auto &FooVal = getFormula(*FooDecl, Env); 5309 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5310 }, 5311 {BuiltinOptions{ContextSensitiveOptions{}}}); 5312 } 5313 5314 TEST(TransferTest, ContextSensitiveConstructorDefault) { 5315 std::string Code = R"( 5316 class MyClass { 5317 public: 5318 MyClass() = default; 5319 5320 bool MyField = true; 5321 }; 5322 5323 void target() { 5324 MyClass MyObj; 5325 bool Foo = MyObj.MyField; 5326 // [[p]] 5327 } 5328 )"; 5329 runDataflow( 5330 Code, 5331 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5332 ASTContext &ASTCtx) { 5333 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5334 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5335 5336 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5337 ASSERT_THAT(FooDecl, NotNull()); 5338 5339 auto &FooVal = getFormula(*FooDecl, Env); 5340 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5341 }, 5342 {BuiltinOptions{ContextSensitiveOptions{}}}); 5343 } 5344 5345 TEST(TransferTest, UnnamedBitfieldInitializer) { 5346 std::string Code = R"( 5347 struct B {}; 5348 struct A { 5349 unsigned a; 5350 unsigned : 4; 5351 unsigned c; 5352 B b; 5353 }; 5354 void target() { 5355 A a = {}; 5356 A test = a; 5357 (void)test.c; 5358 } 5359 )"; 5360 runDataflow( 5361 Code, 5362 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5363 ASTContext &ASTCtx) { 5364 // This doesn't need a body because this test was crashing the framework 5365 // before handling correctly Unnamed bitfields in `InitListExpr`. 5366 }); 5367 } 5368 5369 // Repro for a crash that used to occur with chained short-circuiting logical 5370 // operators. 5371 TEST(TransferTest, ChainedLogicalOps) { 5372 std::string Code = R"( 5373 bool target() { 5374 bool b = true || false || false || false; 5375 // [[p]] 5376 return b; 5377 } 5378 )"; 5379 runDataflow( 5380 Code, 5381 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5382 ASTContext &ASTCtx) { 5383 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5384 auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula(); 5385 EXPECT_TRUE(Env.flowConditionImplies(B)); 5386 }); 5387 } 5388 5389 // Repro for a crash that used to occur when we call a `noreturn` function 5390 // within one of the operands of a `&&` or `||` operator. 5391 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) { 5392 std::string Code = R"( 5393 __attribute__((noreturn)) int doesnt_return(); 5394 bool some_condition(); 5395 void target(bool b1, bool b2) { 5396 // Neither of these should crash. In addition, if we don't terminate the 5397 // program, we know that the operators need to trigger the short-circuit 5398 // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr` 5399 // will be true. 5400 bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0; 5401 bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0; 5402 5403 // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the 5404 // entire expression unreachable. So we know that in both of the following 5405 // cases, if `target()` terminates, the `else` branch was taken. 5406 bool NoreturnOnLhsMakesAndUnreachable = false; 5407 if (some_condition()) 5408 doesnt_return() > 0 && some_condition(); 5409 else 5410 NoreturnOnLhsMakesAndUnreachable = true; 5411 5412 bool NoreturnOnLhsMakesOrUnreachable = false; 5413 if (some_condition()) 5414 doesnt_return() > 0 || some_condition(); 5415 else 5416 NoreturnOnLhsMakesOrUnreachable = true; 5417 5418 // [[p]] 5419 } 5420 )"; 5421 runDataflow( 5422 Code, 5423 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5424 ASTContext &ASTCtx) { 5425 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5426 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5427 auto &A = Env.arena(); 5428 5429 // Check that [[p]] is reachable with a non-false flow condition. 5430 EXPECT_FALSE(Env.flowConditionImplies(A.makeLiteral(false))); 5431 5432 auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula(); 5433 EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(B1))); 5434 5435 auto &NoreturnOnRhsOfAnd = 5436 getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula(); 5437 EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(NoreturnOnRhsOfAnd))); 5438 5439 auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula(); 5440 EXPECT_TRUE(Env.flowConditionImplies(B2)); 5441 5442 auto &NoreturnOnRhsOfOr = 5443 getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr") 5444 .formula(); 5445 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnRhsOfOr)); 5446 5447 auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>( 5448 ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula(); 5449 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesAndUnreachable)); 5450 5451 auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>( 5452 ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula(); 5453 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesOrUnreachable)); 5454 }); 5455 } 5456 5457 TEST(TransferTest, NewExpressions) { 5458 std::string Code = R"( 5459 void target() { 5460 int *p = new int(42); 5461 // [[after_new]] 5462 } 5463 )"; 5464 runDataflow( 5465 Code, 5466 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5467 ASTContext &ASTCtx) { 5468 const Environment &Env = 5469 getEnvironmentAtAnnotation(Results, "after_new"); 5470 5471 auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p"); 5472 5473 EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull()); 5474 }); 5475 } 5476 5477 TEST(TransferTest, NewExpressions_Structs) { 5478 std::string Code = R"( 5479 struct Inner { 5480 int InnerField; 5481 }; 5482 5483 struct Outer { 5484 Inner OuterField; 5485 }; 5486 5487 void target() { 5488 Outer *p = new Outer; 5489 // Access the fields to make sure the analysis actually generates children 5490 // for them in the `RecordStorageLocation` and `RecordValue`. 5491 p->OuterField.InnerField; 5492 // [[after_new]] 5493 } 5494 )"; 5495 runDataflow( 5496 Code, 5497 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5498 ASTContext &ASTCtx) { 5499 const Environment &Env = 5500 getEnvironmentAtAnnotation(Results, "after_new"); 5501 5502 const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField"); 5503 const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField"); 5504 5505 auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p"); 5506 5507 auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc()); 5508 auto &OuterFieldLoc = 5509 *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField)); 5510 auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField); 5511 5512 // Values for the struct and all fields exist after the new. 5513 EXPECT_THAT(Env.getValue(OuterLoc), NotNull()); 5514 EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull()); 5515 EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull()); 5516 }); 5517 } 5518 5519 TEST(TransferTest, FunctionToPointerDecayHasValue) { 5520 std::string Code = R"( 5521 struct A { static void static_member_func(); }; 5522 void target() { 5523 // To check that we're treating function-to-pointer decay correctly, 5524 // create two pointers, then verify they refer to the same storage 5525 // location. 5526 // We need to do the test this way because even if an initializer (in this 5527 // case, the function-to-pointer decay) does not create a value, we still 5528 // create a value for the variable. 5529 void (*non_member_p1)() = target; 5530 void (*non_member_p2)() = target; 5531 5532 // Do the same thing but for a static member function. 5533 void (*member_p1)() = A::static_member_func; 5534 void (*member_p2)() = A::static_member_func; 5535 // [[p]] 5536 } 5537 )"; 5538 runDataflow( 5539 Code, 5540 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5541 ASTContext &ASTCtx) { 5542 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5543 5544 auto &NonMemberP1 = 5545 getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1"); 5546 auto &NonMemberP2 = 5547 getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2"); 5548 EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc()); 5549 5550 auto &MemberP1 = 5551 getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1"); 5552 auto &MemberP2 = 5553 getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2"); 5554 EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc()); 5555 }); 5556 } 5557 5558 // Check that a builtin function is not associated with a value. (It's only 5559 // possible to call builtin functions directly, not take their address.) 5560 TEST(TransferTest, BuiltinFunctionModeled) { 5561 std::string Code = R"( 5562 void target() { 5563 __builtin_expect(0, 0); 5564 // [[p]] 5565 } 5566 )"; 5567 runDataflow( 5568 Code, 5569 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5570 ASTContext &ASTCtx) { 5571 using ast_matchers::selectFirst; 5572 using ast_matchers::match; 5573 using ast_matchers::traverse; 5574 using ast_matchers::implicitCastExpr; 5575 using ast_matchers::hasCastKind; 5576 5577 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5578 5579 auto *ImplicitCast = selectFirst<ImplicitCastExpr>( 5580 "implicit_cast", 5581 match(traverse(TK_AsIs, 5582 implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr)) 5583 .bind("implicit_cast")), 5584 ASTCtx)); 5585 5586 ASSERT_THAT(ImplicitCast, NotNull()); 5587 EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull()); 5588 }); 5589 } 5590 5591 // Check that fields of anonymous records are modeled. 5592 TEST(TransferTest, AnonymousStruct) { 5593 std::string Code = R"( 5594 struct S { 5595 struct { 5596 bool b; 5597 }; 5598 }; 5599 void target() { 5600 S s; 5601 s.b = true; 5602 // [[p]] 5603 } 5604 )"; 5605 runDataflow( 5606 Code, 5607 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5608 ASTContext &ASTCtx) { 5609 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5610 const ValueDecl *SDecl = findValueDecl(ASTCtx, "s"); 5611 const ValueDecl *BDecl = findValueDecl(ASTCtx, "b"); 5612 const IndirectFieldDecl *IndirectField = 5613 findIndirectFieldDecl(ASTCtx, "b"); 5614 5615 auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl)); 5616 auto &AnonStruct = *cast<RecordStorageLocation>( 5617 S->getChild(*cast<ValueDecl>(IndirectField->chain().front()))); 5618 5619 auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env)); 5620 ASSERT_TRUE(Env.flowConditionImplies(B->formula())); 5621 }); 5622 } 5623 5624 TEST(TransferTest, AnonymousStructWithInitializer) { 5625 std::string Code = R"( 5626 struct target { 5627 target() { 5628 (void)0; 5629 // [[p]] 5630 } 5631 struct { 5632 bool b = true; 5633 }; 5634 }; 5635 )"; 5636 runDataflow( 5637 Code, 5638 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5639 ASTContext &ASTCtx) { 5640 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5641 const ValueDecl *BDecl = findValueDecl(ASTCtx, "b"); 5642 const IndirectFieldDecl *IndirectField = 5643 findIndirectFieldDecl(ASTCtx, "b"); 5644 5645 auto *ThisLoc = 5646 cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation()); 5647 auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild( 5648 *cast<ValueDecl>(IndirectField->chain().front()))); 5649 5650 auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env)); 5651 ASSERT_TRUE(Env.flowConditionImplies(B->formula())); 5652 }); 5653 } 5654 5655 TEST(TransferTest, AnonymousStructWithReferenceField) { 5656 std::string Code = R"( 5657 int global_i = 0; 5658 struct target { 5659 target() { 5660 (void)0; 5661 // [[p]] 5662 } 5663 struct { 5664 int &i = global_i; 5665 }; 5666 }; 5667 )"; 5668 runDataflow( 5669 Code, 5670 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5671 ASTContext &ASTCtx) { 5672 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5673 const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i"); 5674 const ValueDecl *IDecl = findValueDecl(ASTCtx, "i"); 5675 const IndirectFieldDecl *IndirectField = 5676 findIndirectFieldDecl(ASTCtx, "i"); 5677 5678 auto *ThisLoc = 5679 cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation()); 5680 auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild( 5681 *cast<ValueDecl>(IndirectField->chain().front()))); 5682 5683 ASSERT_EQ(AnonStruct.getChild(*IDecl), 5684 Env.getStorageLocation(*GlobalIDecl)); 5685 }); 5686 } 5687 5688 } // namespace 5689