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