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