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 = Env.getThisPointeeStorageLocation(); 1521 ASSERT_THAT(ThisLoc, NotNull()); 1522 1523 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1524 ASSERT_THAT(BarDecl, NotNull()); 1525 1526 const auto *BarLoc = 1527 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1528 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1529 1530 const Value *BarVal = Env.getValue(*BarLoc); 1531 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1532 1533 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1534 ASSERT_THAT(FooDecl, NotNull()); 1535 EXPECT_EQ(Env.getValue(*FooDecl), BarVal); 1536 1537 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1538 ASSERT_THAT(QuxDecl, NotNull()); 1539 1540 ASSERT_TRUE(QuxDecl->getType()->isStructureType()); 1541 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1542 1543 FieldDecl *BazDecl = nullptr; 1544 for (FieldDecl *Field : QuxFields) { 1545 if (Field->getNameAsString() == "Baz") { 1546 BazDecl = Field; 1547 } else { 1548 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1549 } 1550 } 1551 ASSERT_THAT(BazDecl, NotNull()); 1552 1553 const auto *QuxLoc = 1554 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1555 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1556 ASSERT_THAT(QuxVal, NotNull()); 1557 1558 const auto *BazLoc = 1559 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1560 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1561 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1562 1563 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1564 ASSERT_THAT(QuuxDecl, NotNull()); 1565 EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal); 1566 }); 1567 } 1568 1569 TEST(TransferTest, ClassThisMember) { 1570 std::string Code = R"( 1571 class A { 1572 int Bar; 1573 1574 class B { 1575 public: 1576 int Baz; 1577 }; 1578 1579 B Qux; 1580 1581 void target() { 1582 int Foo = Bar; 1583 int Quux = Qux.Baz; 1584 // [[p]] 1585 } 1586 }; 1587 )"; 1588 runDataflow( 1589 Code, 1590 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1591 ASTContext &ASTCtx) { 1592 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1593 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1594 1595 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1596 1597 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1598 ASSERT_THAT(BarDecl, NotNull()); 1599 1600 const auto *BarLoc = 1601 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1602 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1603 1604 const Value *BarVal = Env.getValue(*BarLoc); 1605 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1606 1607 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1608 ASSERT_THAT(FooDecl, NotNull()); 1609 EXPECT_EQ(Env.getValue(*FooDecl), BarVal); 1610 1611 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1612 ASSERT_THAT(QuxDecl, NotNull()); 1613 1614 ASSERT_TRUE(QuxDecl->getType()->isClassType()); 1615 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1616 1617 FieldDecl *BazDecl = nullptr; 1618 for (FieldDecl *Field : QuxFields) { 1619 if (Field->getNameAsString() == "Baz") { 1620 BazDecl = Field; 1621 } else { 1622 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1623 } 1624 } 1625 ASSERT_THAT(BazDecl, NotNull()); 1626 1627 const auto *QuxLoc = 1628 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1629 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1630 ASSERT_THAT(QuxVal, NotNull()); 1631 1632 const auto *BazLoc = 1633 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1634 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1635 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1636 1637 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1638 ASSERT_THAT(QuuxDecl, NotNull()); 1639 EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal); 1640 }); 1641 } 1642 1643 TEST(TransferTest, UnionThisMember) { 1644 std::string Code = R"( 1645 union A { 1646 int Foo; 1647 int Bar; 1648 1649 void target() { 1650 A a; 1651 // Mention the fields to ensure they're included in the analysis. 1652 (void)a.Foo; 1653 (void)a.Bar; 1654 // [[p]] 1655 } 1656 }; 1657 )"; 1658 runDataflow( 1659 Code, 1660 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1661 ASTContext &ASTCtx) { 1662 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1663 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1664 1665 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1666 ASSERT_THAT(ThisLoc, NotNull()); 1667 1668 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1669 ASSERT_THAT(FooDecl, NotNull()); 1670 1671 const auto *FooLoc = 1672 cast<ScalarStorageLocation>(&ThisLoc->getChild(*FooDecl)); 1673 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 1674 1675 const Value *FooVal = Env.getValue(*FooLoc); 1676 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 1677 1678 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1679 ASSERT_THAT(BarDecl, NotNull()); 1680 1681 const auto *BarLoc = 1682 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1683 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1684 1685 const Value *BarVal = Env.getValue(*BarLoc); 1686 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1687 }); 1688 } 1689 1690 TEST(TransferTest, StructThisInLambda) { 1691 std::string ThisCaptureCode = R"( 1692 struct A { 1693 void frob() { 1694 [this]() { 1695 int Foo = Bar; 1696 // [[p1]] 1697 }(); 1698 } 1699 1700 int Bar; 1701 }; 1702 )"; 1703 runDataflow( 1704 ThisCaptureCode, 1705 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1706 ASTContext &ASTCtx) { 1707 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1")); 1708 const Environment &Env = getEnvironmentAtAnnotation(Results, "p1"); 1709 1710 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1711 ASSERT_THAT(ThisLoc, NotNull()); 1712 1713 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1714 ASSERT_THAT(BarDecl, NotNull()); 1715 1716 const auto *BarLoc = 1717 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1718 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1719 1720 const Value *BarVal = Env.getValue(*BarLoc); 1721 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1722 1723 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1724 ASSERT_THAT(FooDecl, NotNull()); 1725 EXPECT_EQ(Env.getValue(*FooDecl), BarVal); 1726 }, 1727 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1728 1729 std::string RefCaptureDefaultCode = R"( 1730 struct A { 1731 void frob() { 1732 [&]() { 1733 int Foo = Bar; 1734 // [[p2]] 1735 }(); 1736 } 1737 1738 int Bar; 1739 }; 1740 )"; 1741 runDataflow( 1742 RefCaptureDefaultCode, 1743 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1744 ASTContext &ASTCtx) { 1745 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2")); 1746 const Environment &Env = getEnvironmentAtAnnotation(Results, "p2"); 1747 1748 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1749 ASSERT_THAT(ThisLoc, NotNull()); 1750 1751 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1752 ASSERT_THAT(BarDecl, NotNull()); 1753 1754 const auto *BarLoc = 1755 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1756 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1757 1758 const Value *BarVal = Env.getValue(*BarLoc); 1759 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1760 1761 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1762 ASSERT_THAT(FooDecl, NotNull()); 1763 EXPECT_EQ(Env.getValue(*FooDecl), BarVal); 1764 }, 1765 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1766 1767 std::string FreeFunctionLambdaCode = R"( 1768 void foo() { 1769 int Bar; 1770 [&]() { 1771 int Foo = Bar; 1772 // [[p3]] 1773 }(); 1774 } 1775 )"; 1776 runDataflow( 1777 FreeFunctionLambdaCode, 1778 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1779 ASTContext &ASTCtx) { 1780 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3")); 1781 const Environment &Env = getEnvironmentAtAnnotation(Results, "p3"); 1782 1783 EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull()); 1784 }, 1785 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1786 } 1787 1788 TEST(TransferTest, ConstructorInitializer) { 1789 std::string Code = R"( 1790 struct target { 1791 int Bar; 1792 1793 target(int Foo) : Bar(Foo) { 1794 int Qux = Bar; 1795 // [[p]] 1796 } 1797 }; 1798 )"; 1799 runDataflow( 1800 Code, 1801 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1802 ASTContext &ASTCtx) { 1803 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1804 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1805 1806 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1807 ASSERT_THAT(ThisLoc, NotNull()); 1808 1809 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1810 ASSERT_THAT(FooDecl, NotNull()); 1811 1812 const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl)); 1813 1814 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1815 ASSERT_THAT(QuxDecl, NotNull()); 1816 EXPECT_EQ(Env.getValue(*QuxDecl), FooVal); 1817 }); 1818 } 1819 1820 TEST(TransferTest, DefaultInitializer) { 1821 std::string Code = R"( 1822 struct target { 1823 int Bar; 1824 int Baz = Bar; 1825 1826 target(int Foo) : Bar(Foo) { 1827 int Qux = Baz; 1828 // [[p]] 1829 } 1830 }; 1831 )"; 1832 runDataflow( 1833 Code, 1834 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1835 ASTContext &ASTCtx) { 1836 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1837 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1838 1839 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1840 ASSERT_THAT(ThisLoc, NotNull()); 1841 1842 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1843 ASSERT_THAT(FooDecl, NotNull()); 1844 1845 const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl)); 1846 1847 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1848 ASSERT_THAT(QuxDecl, NotNull()); 1849 EXPECT_EQ(Env.getValue(*QuxDecl), FooVal); 1850 }); 1851 } 1852 1853 TEST(TransferTest, DefaultInitializerReference) { 1854 std::string Code = R"( 1855 struct target { 1856 int &Bar; 1857 int &Baz = Bar; 1858 1859 target(int &Foo) : Bar(Foo) { 1860 int &Qux = Baz; 1861 // [[p]] 1862 } 1863 }; 1864 )"; 1865 runDataflow( 1866 Code, 1867 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1868 ASTContext &ASTCtx) { 1869 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1870 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1871 1872 const auto *ThisLoc = Env.getThisPointeeStorageLocation(); 1873 ASSERT_THAT(ThisLoc, NotNull()); 1874 1875 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1876 ASSERT_THAT(FooDecl, NotNull()); 1877 1878 const auto *FooLoc = Env.getStorageLocation(*FooDecl); 1879 1880 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1881 ASSERT_THAT(QuxDecl, NotNull()); 1882 1883 const auto *QuxLoc = Env.getStorageLocation(*QuxDecl); 1884 EXPECT_EQ(QuxLoc, FooLoc); 1885 }); 1886 } 1887 1888 TEST(TransferTest, TemporaryObject) { 1889 std::string Code = R"( 1890 struct A { 1891 int Bar; 1892 }; 1893 1894 void target() { 1895 A Foo = A(); 1896 (void)Foo.Bar; 1897 // [[p]] 1898 } 1899 )"; 1900 runDataflow( 1901 Code, 1902 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1903 ASTContext &ASTCtx) { 1904 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1905 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1906 1907 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1908 ASSERT_THAT(FooDecl, NotNull()); 1909 1910 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1911 ASSERT_THAT(BarDecl, NotNull()); 1912 1913 const auto *FooLoc = 1914 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 1915 const auto *BarLoc = 1916 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1917 1918 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1919 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1920 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1921 }); 1922 } 1923 1924 TEST(TransferTest, ElidableConstructor) { 1925 // This test is effectively the same as TransferTest.TemporaryObject, but 1926 // the code is compiled as C++ 14. 1927 std::string Code = R"( 1928 struct A { 1929 int Bar; 1930 }; 1931 1932 void target() { 1933 A Foo = A(); 1934 (void)Foo.Bar; 1935 // [[p]] 1936 } 1937 )"; 1938 runDataflow( 1939 Code, 1940 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1941 ASTContext &ASTCtx) { 1942 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1943 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1944 1945 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1946 ASSERT_THAT(FooDecl, NotNull()); 1947 1948 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1949 ASSERT_THAT(BarDecl, NotNull()); 1950 1951 const auto *FooLoc = 1952 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 1953 const auto *BarLoc = 1954 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1955 1956 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1957 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1958 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1959 }, 1960 LangStandard::lang_cxx14); 1961 } 1962 1963 TEST(TransferTest, AssignmentOperator) { 1964 std::string Code = R"( 1965 struct A { 1966 int Baz; 1967 }; 1968 1969 void target() { 1970 A Foo = { 1 }; 1971 A Bar = { 2 }; 1972 // [[p1]] 1973 Foo = Bar; 1974 // [[p2]] 1975 Foo.Baz = 3; 1976 // [[p3]] 1977 } 1978 )"; 1979 runDataflow( 1980 Code, 1981 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1982 ASTContext &ASTCtx) { 1983 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1984 ASSERT_THAT(FooDecl, NotNull()); 1985 1986 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1987 ASSERT_THAT(BarDecl, NotNull()); 1988 1989 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1990 ASSERT_THAT(BazDecl, NotNull()); 1991 1992 // Before copy assignment. 1993 { 1994 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 1995 1996 const auto *FooLoc1 = 1997 cast<AggregateStorageLocation>(Env1.getStorageLocation(*FooDecl)); 1998 const auto *BarLoc1 = 1999 cast<AggregateStorageLocation>(Env1.getStorageLocation(*BarDecl)); 2000 EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1)); 2001 2002 const auto *FooBazVal1 = 2003 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 2004 const auto *BarBazVal1 = 2005 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 2006 EXPECT_NE(FooBazVal1, BarBazVal1); 2007 } 2008 2009 // After copy assignment. 2010 { 2011 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 2012 2013 const auto *FooLoc2 = 2014 cast<AggregateStorageLocation>(Env2.getStorageLocation(*FooDecl)); 2015 const auto *BarLoc2 = 2016 cast<AggregateStorageLocation>(Env2.getStorageLocation(*BarDecl)); 2017 2018 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 2019 const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2)); 2020 EXPECT_NE(FooVal2, BarVal2); 2021 2022 EXPECT_TRUE(recordsEqual(*FooLoc2, *BarLoc2, Env2)); 2023 2024 const auto *FooBazVal2 = 2025 cast<IntegerValue>(Env2.getValue(FooLoc2->getChild(*BazDecl))); 2026 const auto *BarBazVal2 = 2027 cast<IntegerValue>(Env2.getValue(BarLoc2->getChild(*BazDecl))); 2028 EXPECT_EQ(FooBazVal2, BarBazVal2); 2029 } 2030 2031 // After value update. 2032 { 2033 const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3"); 2034 2035 const auto *FooLoc3 = 2036 cast<AggregateStorageLocation>(Env3.getStorageLocation(*FooDecl)); 2037 const auto *BarLoc3 = 2038 cast<AggregateStorageLocation>(Env3.getStorageLocation(*BarDecl)); 2039 EXPECT_FALSE(recordsEqual(*FooLoc3, *BarLoc3, Env3)); 2040 2041 const auto *FooBazVal3 = 2042 cast<IntegerValue>(Env3.getValue(FooLoc3->getChild(*BazDecl))); 2043 const auto *BarBazVal3 = 2044 cast<IntegerValue>(Env3.getValue(BarLoc3->getChild(*BazDecl))); 2045 EXPECT_NE(FooBazVal3, BarBazVal3); 2046 } 2047 }); 2048 } 2049 2050 TEST(TransferTest, AssignmentOperatorFromCallResult) { 2051 std::string Code = R"( 2052 struct A {}; 2053 A ReturnA(); 2054 2055 void target() { 2056 A MyA; 2057 MyA = ReturnA(); 2058 } 2059 )"; 2060 runDataflow( 2061 Code, 2062 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2063 ASTContext &ASTCtx) { 2064 // As of this writing, we don't produce a `Value` for the call 2065 // `ReturnA()`. The only condition we're testing for is that the 2066 // analysis should not crash in this case. 2067 }); 2068 } 2069 2070 TEST(TransferTest, CopyConstructor) { 2071 std::string Code = R"( 2072 struct A { 2073 int Baz; 2074 }; 2075 2076 void target() { 2077 A Foo = { 1 }; 2078 A Bar = Foo; 2079 // [[after_copy]] 2080 Foo.Baz = 2; 2081 // [[after_update]] 2082 } 2083 )"; 2084 runDataflow( 2085 Code, 2086 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2087 ASTContext &ASTCtx) { 2088 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2089 ASSERT_THAT(FooDecl, NotNull()); 2090 2091 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2092 ASSERT_THAT(BarDecl, NotNull()); 2093 2094 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2095 ASSERT_THAT(BazDecl, NotNull()); 2096 2097 // after_copy 2098 { 2099 const Environment &Env = 2100 getEnvironmentAtAnnotation(Results, "after_copy"); 2101 2102 const auto *FooLoc = 2103 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 2104 const auto *BarLoc = 2105 cast<AggregateStorageLocation>(Env.getStorageLocation(*BarDecl)); 2106 2107 // `Foo` and `Bar` have different `StructValue`s associated with them. 2108 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 2109 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 2110 EXPECT_NE(FooVal, BarVal); 2111 2112 // But the records compare equal. 2113 EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env)); 2114 2115 // In particular, the value of `Baz` in both records is the same. 2116 const auto *FooBazVal = 2117 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 2118 const auto *BarBazVal = 2119 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 2120 EXPECT_EQ(FooBazVal, BarBazVal); 2121 } 2122 2123 // after_update 2124 { 2125 const Environment &Env = 2126 getEnvironmentAtAnnotation(Results, "after_update"); 2127 2128 const auto *FooLoc = 2129 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 2130 const auto *BarLoc = 2131 cast<AggregateStorageLocation>(Env.getStorageLocation(*BarDecl)); 2132 2133 EXPECT_FALSE(recordsEqual(*FooLoc, *BarLoc, Env)); 2134 2135 const auto *FooBazVal = 2136 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 2137 const auto *BarBazVal = 2138 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 2139 EXPECT_NE(FooBazVal, BarBazVal); 2140 } 2141 }); 2142 } 2143 2144 TEST(TransferTest, CopyConstructorWithDefaultArgument) { 2145 std::string Code = R"( 2146 struct A { 2147 int Baz; 2148 A() = default; 2149 A(const A& a, bool def = true) { Baz = a.Baz; } 2150 }; 2151 2152 void target() { 2153 A Foo; 2154 (void)Foo.Baz; 2155 A Bar = Foo; 2156 // [[p]] 2157 } 2158 )"; 2159 runDataflow( 2160 Code, 2161 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2162 ASTContext &ASTCtx) { 2163 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2164 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2165 2166 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2167 ASSERT_THAT(FooDecl, NotNull()); 2168 2169 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2170 ASSERT_THAT(BarDecl, NotNull()); 2171 2172 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2173 ASSERT_THAT(BazDecl, NotNull()); 2174 2175 const auto *FooLoc = 2176 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 2177 const auto *BarLoc = 2178 cast<AggregateStorageLocation>(Env.getStorageLocation(*BarDecl)); 2179 EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env)); 2180 2181 const auto *FooBazVal = 2182 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 2183 const auto *BarBazVal = 2184 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 2185 EXPECT_EQ(FooBazVal, BarBazVal); 2186 }); 2187 } 2188 2189 TEST(TransferTest, CopyConstructorWithParens) { 2190 std::string Code = R"( 2191 struct A { 2192 int Baz; 2193 }; 2194 2195 void target() { 2196 A Foo; 2197 (void)Foo.Baz; 2198 A Bar((A(Foo))); 2199 // [[p]] 2200 } 2201 )"; 2202 runDataflow( 2203 Code, 2204 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2205 ASTContext &ASTCtx) { 2206 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2207 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2208 2209 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2210 ASSERT_THAT(FooDecl, NotNull()); 2211 2212 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2213 ASSERT_THAT(BarDecl, NotNull()); 2214 2215 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2216 ASSERT_THAT(BazDecl, NotNull()); 2217 2218 const auto *FooLoc = 2219 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 2220 const auto *BarLoc = 2221 cast<AggregateStorageLocation>(Env.getStorageLocation(*BarDecl)); 2222 EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env)); 2223 2224 const auto *FooBazVal = 2225 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 2226 const auto *BarBazVal = 2227 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 2228 EXPECT_EQ(FooBazVal, BarBazVal); 2229 }); 2230 } 2231 2232 TEST(TransferTest, CopyConstructorArgIsRefReturnedByFunction) { 2233 // This is a crash repro. 2234 std::string Code = R"( 2235 struct S {}; 2236 const S &returnsSRef(); 2237 void target() { 2238 S s(returnsSRef()); 2239 } 2240 )"; 2241 runDataflow( 2242 Code, 2243 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2244 ASTContext &ASTCtx) {}); 2245 } 2246 2247 TEST(TransferTest, MoveConstructor) { 2248 std::string Code = R"( 2249 namespace std { 2250 2251 template <typename T> struct remove_reference { using type = T; }; 2252 template <typename T> struct remove_reference<T&> { using type = T; }; 2253 template <typename T> struct remove_reference<T&&> { using type = T; }; 2254 2255 template <typename T> 2256 using remove_reference_t = typename remove_reference<T>::type; 2257 2258 template <typename T> 2259 std::remove_reference_t<T>&& move(T&& x); 2260 2261 } // namespace std 2262 2263 struct A { 2264 int Baz; 2265 }; 2266 2267 void target() { 2268 A Foo; 2269 A Bar; 2270 (void)Foo.Baz; 2271 // [[p1]] 2272 Foo = std::move(Bar); 2273 // [[p2]] 2274 } 2275 )"; 2276 runDataflow( 2277 Code, 2278 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2279 ASTContext &ASTCtx) { 2280 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 2281 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 2282 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 2283 2284 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2285 ASSERT_THAT(FooDecl, NotNull()); 2286 2287 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2288 ASSERT_THAT(BarDecl, NotNull()); 2289 2290 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2291 ASSERT_THAT(BazDecl, NotNull()); 2292 2293 const auto *FooLoc1 = 2294 cast<AggregateStorageLocation>(Env1.getStorageLocation(*FooDecl)); 2295 const auto *BarLoc1 = 2296 cast<AggregateStorageLocation>(Env1.getStorageLocation(*BarDecl)); 2297 2298 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 2299 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 2300 EXPECT_NE(FooVal1, BarVal1); 2301 2302 EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1)); 2303 2304 const auto *FooBazVal1 = 2305 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 2306 const auto *BarBazVal1 = 2307 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 2308 EXPECT_NE(FooBazVal1, BarBazVal1); 2309 2310 const auto *FooLoc2 = 2311 cast<AggregateStorageLocation>(Env2.getStorageLocation(*FooDecl)); 2312 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 2313 EXPECT_NE(FooVal2, BarVal1); 2314 EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1)); 2315 2316 const auto *FooBazVal2 = 2317 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 2318 EXPECT_EQ(FooBazVal2, BarBazVal1); 2319 }); 2320 } 2321 2322 TEST(TransferTest, BindTemporary) { 2323 std::string Code = R"( 2324 struct A { 2325 virtual ~A() = default; 2326 2327 int Baz; 2328 }; 2329 2330 void target(A Foo) { 2331 int Bar = A(Foo).Baz; 2332 // [[p]] 2333 } 2334 )"; 2335 runDataflow( 2336 Code, 2337 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2338 ASTContext &ASTCtx) { 2339 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2340 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2341 2342 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2343 ASSERT_THAT(FooDecl, NotNull()); 2344 2345 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2346 ASSERT_THAT(BarDecl, NotNull()); 2347 2348 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2349 ASSERT_THAT(BazDecl, NotNull()); 2350 2351 const auto &FooVal = *cast<StructValue>(Env.getValue(*FooDecl)); 2352 const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 2353 EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl)); 2354 }); 2355 } 2356 2357 TEST(TransferTest, StaticCast) { 2358 std::string Code = R"( 2359 void target(int Foo) { 2360 int Bar = static_cast<int>(Foo); 2361 // [[p]] 2362 } 2363 )"; 2364 runDataflow( 2365 Code, 2366 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2367 ASTContext &ASTCtx) { 2368 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2369 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2370 2371 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2372 ASSERT_THAT(FooDecl, NotNull()); 2373 2374 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2375 ASSERT_THAT(BarDecl, NotNull()); 2376 2377 const auto *FooVal = Env.getValue(*FooDecl); 2378 const auto *BarVal = Env.getValue(*BarDecl); 2379 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2380 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2381 EXPECT_EQ(FooVal, BarVal); 2382 }); 2383 } 2384 2385 TEST(TransferTest, IntegralCast) { 2386 std::string Code = R"( 2387 void target(int Foo) { 2388 long Bar = Foo; 2389 // [[p]] 2390 } 2391 )"; 2392 runDataflow( 2393 Code, 2394 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2395 ASTContext &ASTCtx) { 2396 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2397 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2398 2399 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2400 ASSERT_THAT(FooDecl, NotNull()); 2401 2402 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2403 ASSERT_THAT(BarDecl, NotNull()); 2404 2405 const auto *FooVal = Env.getValue(*FooDecl); 2406 const auto *BarVal = Env.getValue(*BarDecl); 2407 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2408 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2409 EXPECT_EQ(FooVal, BarVal); 2410 }); 2411 } 2412 2413 TEST(TransferTest, IntegraltoBooleanCast) { 2414 std::string Code = R"( 2415 void target(int Foo) { 2416 bool Bar = Foo; 2417 // [[p]] 2418 } 2419 )"; 2420 runDataflow( 2421 Code, 2422 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2423 ASTContext &ASTCtx) { 2424 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2425 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2426 2427 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2428 ASSERT_THAT(FooDecl, NotNull()); 2429 2430 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2431 ASSERT_THAT(BarDecl, NotNull()); 2432 2433 const auto *FooVal = Env.getValue(*FooDecl); 2434 const auto *BarVal = Env.getValue(*BarDecl); 2435 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2436 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2437 }); 2438 } 2439 2440 TEST(TransferTest, IntegralToBooleanCastFromBool) { 2441 std::string Code = R"( 2442 void target(bool Foo) { 2443 int Zab = Foo; 2444 bool Bar = Zab; 2445 // [[p]] 2446 } 2447 )"; 2448 runDataflow( 2449 Code, 2450 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2451 ASTContext &ASTCtx) { 2452 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2453 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2454 2455 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2456 ASSERT_THAT(FooDecl, NotNull()); 2457 2458 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2459 ASSERT_THAT(BarDecl, NotNull()); 2460 2461 const auto *FooVal = Env.getValue(*FooDecl); 2462 const auto *BarVal = Env.getValue(*BarDecl); 2463 EXPECT_TRUE(isa<BoolValue>(FooVal)); 2464 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2465 EXPECT_EQ(FooVal, BarVal); 2466 }); 2467 } 2468 2469 TEST(TransferTest, NullToPointerCast) { 2470 std::string Code = R"( 2471 using my_nullptr_t = decltype(nullptr); 2472 struct Baz {}; 2473 void target() { 2474 int *FooX = nullptr; 2475 int *FooY = nullptr; 2476 bool **Bar = nullptr; 2477 Baz *Baz = nullptr; 2478 my_nullptr_t Null = 0; 2479 // [[p]] 2480 } 2481 )"; 2482 runDataflow( 2483 Code, 2484 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2485 ASTContext &ASTCtx) { 2486 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2487 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2488 2489 const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX"); 2490 ASSERT_THAT(FooXDecl, NotNull()); 2491 2492 const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY"); 2493 ASSERT_THAT(FooYDecl, NotNull()); 2494 2495 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2496 ASSERT_THAT(BarDecl, NotNull()); 2497 2498 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2499 ASSERT_THAT(BazDecl, NotNull()); 2500 2501 const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null"); 2502 ASSERT_THAT(NullDecl, NotNull()); 2503 2504 const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl)); 2505 const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl)); 2506 const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl)); 2507 const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl)); 2508 const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl)); 2509 2510 EXPECT_EQ(FooXVal, FooYVal); 2511 EXPECT_NE(FooXVal, BarVal); 2512 EXPECT_NE(FooXVal, BazVal); 2513 EXPECT_NE(BarVal, BazVal); 2514 2515 const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc(); 2516 EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc)); 2517 EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull()); 2518 2519 const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc(); 2520 EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc)); 2521 EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull()); 2522 2523 const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc(); 2524 EXPECT_TRUE(isa<AggregateStorageLocation>(BazPointeeLoc)); 2525 EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull()); 2526 2527 const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc(); 2528 EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc)); 2529 EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull()); 2530 }); 2531 } 2532 2533 TEST(TransferTest, NullToMemberPointerCast) { 2534 std::string Code = R"( 2535 struct Foo {}; 2536 void target(Foo *Foo) { 2537 int Foo::*MemberPointer = nullptr; 2538 // [[p]] 2539 } 2540 )"; 2541 runDataflow( 2542 Code, 2543 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2544 ASTContext &ASTCtx) { 2545 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2546 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2547 2548 const ValueDecl *MemberPointerDecl = 2549 findValueDecl(ASTCtx, "MemberPointer"); 2550 ASSERT_THAT(MemberPointerDecl, NotNull()); 2551 2552 const auto *MemberPointerVal = 2553 cast<PointerValue>(Env.getValue(*MemberPointerDecl)); 2554 2555 const StorageLocation &MemberLoc = MemberPointerVal->getPointeeLoc(); 2556 EXPECT_THAT(Env.getValue(MemberLoc), IsNull()); 2557 }); 2558 } 2559 2560 TEST(TransferTest, AddrOfValue) { 2561 std::string Code = R"( 2562 void target() { 2563 int Foo; 2564 int *Bar = &Foo; 2565 // [[p]] 2566 } 2567 )"; 2568 runDataflow( 2569 Code, 2570 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2571 ASTContext &ASTCtx) { 2572 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2573 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2574 2575 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2576 ASSERT_THAT(FooDecl, NotNull()); 2577 2578 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2579 ASSERT_THAT(BarDecl, NotNull()); 2580 2581 const auto *FooLoc = 2582 cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl)); 2583 const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl)); 2584 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc); 2585 }); 2586 } 2587 2588 TEST(TransferTest, AddrOfReference) { 2589 std::string Code = R"( 2590 void target(int *Foo) { 2591 int *Bar = &(*Foo); 2592 // [[p]] 2593 } 2594 )"; 2595 runDataflow( 2596 Code, 2597 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2598 ASTContext &ASTCtx) { 2599 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2600 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2601 2602 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2603 ASSERT_THAT(FooDecl, NotNull()); 2604 2605 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2606 ASSERT_THAT(BarDecl, NotNull()); 2607 2608 const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl)); 2609 const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl)); 2610 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 2611 }); 2612 } 2613 2614 TEST(TransferTest, CannotAnalyzeFunctionTemplate) { 2615 std::string Code = R"( 2616 template <typename T> 2617 void target() {} 2618 )"; 2619 ASSERT_THAT_ERROR( 2620 runDataflowReturnError( 2621 Code, 2622 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2623 ASTContext &ASTCtx) {}, 2624 {BuiltinOptions()}), 2625 llvm::FailedWithMessage("Cannot analyze templated declarations")); 2626 } 2627 2628 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) { 2629 std::string Code = R"( 2630 template <typename T> 2631 struct A { 2632 void target() {} 2633 }; 2634 )"; 2635 ASSERT_THAT_ERROR( 2636 runDataflowReturnError( 2637 Code, 2638 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2639 ASTContext &ASTCtx) {}, 2640 {BuiltinOptions()}), 2641 llvm::FailedWithMessage("Cannot analyze templated declarations")); 2642 } 2643 2644 TEST(TransferTest, VarDeclInitAssignConditionalOperator) { 2645 std::string Code = R"( 2646 struct A {}; 2647 2648 void target(A Foo, A Bar, bool Cond) { 2649 A Baz = Cond ? Foo : Bar; 2650 /*[[p]]*/ 2651 } 2652 )"; 2653 runDataflow( 2654 Code, 2655 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2656 ASTContext &ASTCtx) { 2657 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2658 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2659 2660 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2661 ASSERT_THAT(FooDecl, NotNull()); 2662 2663 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2664 ASSERT_THAT(BarDecl, NotNull()); 2665 2666 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2667 ASSERT_THAT(BazDecl, NotNull()); 2668 2669 const auto *FooVal = cast<StructValue>(Env.getValue(*FooDecl)); 2670 const auto *BarVal = cast<StructValue>(Env.getValue(*BarDecl)); 2671 2672 const auto *BazVal = dyn_cast<StructValue>(Env.getValue(*BazDecl)); 2673 ASSERT_THAT(BazVal, NotNull()); 2674 2675 EXPECT_NE(BazVal, FooVal); 2676 EXPECT_NE(BazVal, BarVal); 2677 }); 2678 } 2679 2680 TEST(TransferTest, VarDeclInDoWhile) { 2681 std::string Code = R"( 2682 void target(int *Foo) { 2683 do { 2684 int Bar = *Foo; 2685 // [[in_loop]] 2686 } while (false); 2687 (void)0; 2688 // [[after_loop]] 2689 } 2690 )"; 2691 runDataflow( 2692 Code, 2693 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2694 ASTContext &ASTCtx) { 2695 const Environment &EnvInLoop = 2696 getEnvironmentAtAnnotation(Results, "in_loop"); 2697 const Environment &EnvAfterLoop = 2698 getEnvironmentAtAnnotation(Results, "after_loop"); 2699 2700 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2701 ASSERT_THAT(FooDecl, NotNull()); 2702 2703 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2704 ASSERT_THAT(BarDecl, NotNull()); 2705 2706 const auto *FooVal = 2707 cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl)); 2708 const auto *FooPointeeVal = 2709 cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc())); 2710 2711 const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl)); 2712 EXPECT_EQ(BarVal, FooPointeeVal); 2713 2714 // FIXME: This assertion documents current behavior, but we would prefer 2715 // declarations to be removed from the environment when their lifetime 2716 // ends. Once this is the case, change this assertion accordingly. 2717 ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), BarVal); 2718 }); 2719 } 2720 2721 TEST(TransferTest, UnreachableAfterWhileTrue) { 2722 std::string Code = R"( 2723 void target() { 2724 while (true) {} 2725 (void)0; 2726 /*[[p]]*/ 2727 } 2728 )"; 2729 runDataflow( 2730 Code, 2731 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2732 ASTContext &ASTCtx) { 2733 // The node after the while-true is pruned because it is trivially 2734 // known to be unreachable. 2735 ASSERT_TRUE(Results.empty()); 2736 }); 2737 } 2738 2739 TEST(TransferTest, AggregateInitialization) { 2740 std::string BracesCode = R"( 2741 struct A { 2742 int Foo; 2743 }; 2744 2745 struct B { 2746 int Bar; 2747 A Baz; 2748 int Qux; 2749 }; 2750 2751 void target(int BarArg, int FooArg, int QuxArg) { 2752 B Quux{BarArg, {FooArg}, QuxArg}; 2753 /*[[p]]*/ 2754 } 2755 )"; 2756 std::string BraceEllisionCode = R"( 2757 struct A { 2758 int Foo; 2759 }; 2760 2761 struct B { 2762 int Bar; 2763 A Baz; 2764 int Qux; 2765 }; 2766 2767 void target(int BarArg, int FooArg, int QuxArg) { 2768 B Quux = {BarArg, FooArg, QuxArg}; 2769 /*[[p]]*/ 2770 } 2771 )"; 2772 for (const std::string &Code : {BracesCode, BraceEllisionCode}) { 2773 runDataflow( 2774 Code, 2775 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2776 ASTContext &ASTCtx) { 2777 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2778 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2779 2780 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2781 ASSERT_THAT(FooDecl, NotNull()); 2782 2783 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2784 ASSERT_THAT(BarDecl, NotNull()); 2785 2786 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2787 ASSERT_THAT(BazDecl, NotNull()); 2788 2789 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2790 ASSERT_THAT(QuxDecl, NotNull()); 2791 2792 const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg"); 2793 ASSERT_THAT(FooArgDecl, NotNull()); 2794 2795 const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg"); 2796 ASSERT_THAT(BarArgDecl, NotNull()); 2797 2798 const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg"); 2799 ASSERT_THAT(QuxArgDecl, NotNull()); 2800 2801 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 2802 ASSERT_THAT(QuuxDecl, NotNull()); 2803 2804 const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl)); 2805 const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl)); 2806 const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl)); 2807 2808 const auto *QuuxVal = cast<StructValue>(Env.getValue(*QuuxDecl)); 2809 ASSERT_THAT(QuuxVal, NotNull()); 2810 2811 const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl)); 2812 ASSERT_THAT(BazVal, NotNull()); 2813 2814 EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal); 2815 EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal); 2816 EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal); 2817 }); 2818 } 2819 } 2820 2821 TEST(TransferTest, AssignToUnionMember) { 2822 std::string Code = R"( 2823 union A { 2824 int Foo; 2825 }; 2826 2827 void target(int Bar) { 2828 A Baz; 2829 Baz.Foo = Bar; 2830 // [[p]] 2831 } 2832 )"; 2833 runDataflow( 2834 Code, 2835 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2836 ASTContext &ASTCtx) { 2837 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2838 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2839 2840 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2841 ASSERT_THAT(BazDecl, NotNull()); 2842 ASSERT_TRUE(BazDecl->getType()->isUnionType()); 2843 2844 auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields(); 2845 FieldDecl *FooDecl = nullptr; 2846 for (FieldDecl *Field : BazFields) { 2847 if (Field->getNameAsString() == "Foo") { 2848 FooDecl = Field; 2849 } else { 2850 FAIL() << "Unexpected field: " << Field->getNameAsString(); 2851 } 2852 } 2853 ASSERT_THAT(FooDecl, NotNull()); 2854 2855 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>( 2856 Env.getStorageLocation(*BazDecl)); 2857 ASSERT_THAT(BazLoc, NotNull()); 2858 ASSERT_THAT(Env.getValue(*BazLoc), NotNull()); 2859 2860 const auto *BazVal = cast<StructValue>(Env.getValue(*BazLoc)); 2861 const auto *FooValFromBazVal = cast<IntegerValue>(BazVal->getChild(*FooDecl)); 2862 const auto *FooValFromBazLoc = cast<IntegerValue>(Env.getValue(BazLoc->getChild(*FooDecl))); 2863 EXPECT_EQ(FooValFromBazLoc, FooValFromBazVal); 2864 2865 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2866 ASSERT_THAT(BarDecl, NotNull()); 2867 const auto *BarLoc = Env.getStorageLocation(*BarDecl); 2868 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 2869 2870 EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazVal); 2871 EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazLoc); 2872 }); 2873 } 2874 2875 TEST(TransferTest, AssignFromBoolLiteral) { 2876 std::string Code = R"( 2877 void target() { 2878 bool Foo = true; 2879 bool Bar = false; 2880 // [[p]] 2881 } 2882 )"; 2883 runDataflow( 2884 Code, 2885 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2886 ASTContext &ASTCtx) { 2887 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2888 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2889 2890 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2891 ASSERT_THAT(FooDecl, NotNull()); 2892 2893 const auto *FooVal = 2894 dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl)); 2895 ASSERT_THAT(FooVal, NotNull()); 2896 2897 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2898 ASSERT_THAT(BarDecl, NotNull()); 2899 2900 const auto *BarVal = 2901 dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*BarDecl)); 2902 ASSERT_THAT(BarVal, NotNull()); 2903 2904 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true)); 2905 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false)); 2906 }); 2907 } 2908 2909 TEST(TransferTest, AssignFromCompositeBoolExpression) { 2910 { 2911 std::string Code = R"( 2912 void target(bool Foo, bool Bar, bool Qux) { 2913 bool Baz = (Foo) && (Bar || Qux); 2914 // [[p]] 2915 } 2916 )"; 2917 runDataflow( 2918 Code, 2919 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2920 ASTContext &ASTCtx) { 2921 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2922 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2923 2924 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2925 ASSERT_THAT(FooDecl, NotNull()); 2926 2927 const auto *FooVal = 2928 dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl)); 2929 ASSERT_THAT(FooVal, NotNull()); 2930 2931 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2932 ASSERT_THAT(BarDecl, NotNull()); 2933 2934 const auto *BarVal = 2935 dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl)); 2936 ASSERT_THAT(BarVal, NotNull()); 2937 2938 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2939 ASSERT_THAT(QuxDecl, NotNull()); 2940 2941 const auto *QuxVal = 2942 dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl)); 2943 ASSERT_THAT(QuxVal, NotNull()); 2944 2945 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2946 ASSERT_THAT(BazDecl, NotNull()); 2947 2948 const auto *BazVal = 2949 dyn_cast_or_null<ConjunctionValue>(Env.getValue(*BazDecl)); 2950 ASSERT_THAT(BazVal, NotNull()); 2951 EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal); 2952 2953 const auto *BazRightSubValVal = 2954 cast<DisjunctionValue>(&BazVal->getRightSubValue()); 2955 EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal); 2956 EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal); 2957 }); 2958 } 2959 2960 { 2961 std::string Code = R"( 2962 void target(bool Foo, bool Bar, bool Qux) { 2963 bool Baz = (Foo && Qux) || (Bar); 2964 // [[p]] 2965 } 2966 )"; 2967 runDataflow( 2968 Code, 2969 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2970 ASTContext &ASTCtx) { 2971 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2972 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2973 2974 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2975 ASSERT_THAT(FooDecl, NotNull()); 2976 2977 const auto *FooVal = 2978 dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl)); 2979 ASSERT_THAT(FooVal, NotNull()); 2980 2981 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2982 ASSERT_THAT(BarDecl, NotNull()); 2983 2984 const auto *BarVal = 2985 dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl)); 2986 ASSERT_THAT(BarVal, NotNull()); 2987 2988 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2989 ASSERT_THAT(QuxDecl, NotNull()); 2990 2991 const auto *QuxVal = 2992 dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl)); 2993 ASSERT_THAT(QuxVal, NotNull()); 2994 2995 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2996 ASSERT_THAT(BazDecl, NotNull()); 2997 2998 const auto *BazVal = 2999 dyn_cast_or_null<DisjunctionValue>(Env.getValue(*BazDecl)); 3000 ASSERT_THAT(BazVal, NotNull()); 3001 3002 const auto *BazLeftSubValVal = 3003 cast<ConjunctionValue>(&BazVal->getLeftSubValue()); 3004 EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal); 3005 EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal); 3006 3007 EXPECT_EQ(&BazVal->getRightSubValue(), BarVal); 3008 }); 3009 } 3010 3011 { 3012 std::string Code = R"( 3013 void target(bool A, bool B, bool C, bool D) { 3014 bool Foo = ((A && B) && C) && D; 3015 // [[p]] 3016 } 3017 )"; 3018 runDataflow( 3019 Code, 3020 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3021 ASTContext &ASTCtx) { 3022 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3023 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3024 3025 const ValueDecl *ADecl = findValueDecl(ASTCtx, "A"); 3026 ASSERT_THAT(ADecl, NotNull()); 3027 3028 const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl)); 3029 ASSERT_THAT(AVal, NotNull()); 3030 3031 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3032 ASSERT_THAT(BDecl, NotNull()); 3033 3034 const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl)); 3035 ASSERT_THAT(BVal, NotNull()); 3036 3037 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3038 ASSERT_THAT(CDecl, NotNull()); 3039 3040 const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl)); 3041 ASSERT_THAT(CVal, NotNull()); 3042 3043 const ValueDecl *DDecl = findValueDecl(ASTCtx, "D"); 3044 ASSERT_THAT(DDecl, NotNull()); 3045 3046 const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl)); 3047 ASSERT_THAT(DVal, NotNull()); 3048 3049 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3050 ASSERT_THAT(FooDecl, NotNull()); 3051 3052 const auto *FooVal = 3053 dyn_cast_or_null<ConjunctionValue>(Env.getValue(*FooDecl)); 3054 ASSERT_THAT(FooVal, NotNull()); 3055 3056 const auto &FooLeftSubVal = 3057 cast<ConjunctionValue>(FooVal->getLeftSubValue()); 3058 const auto &FooLeftLeftSubVal = 3059 cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue()); 3060 EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal); 3061 EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal); 3062 EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal); 3063 EXPECT_EQ(&FooVal->getRightSubValue(), DVal); 3064 }); 3065 } 3066 } 3067 3068 TEST(TransferTest, AssignFromBoolNegation) { 3069 std::string Code = R"( 3070 void target() { 3071 bool Foo = true; 3072 bool Bar = !(Foo); 3073 // [[p]] 3074 } 3075 )"; 3076 runDataflow( 3077 Code, 3078 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3079 ASTContext &ASTCtx) { 3080 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3081 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3082 3083 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3084 ASSERT_THAT(FooDecl, NotNull()); 3085 3086 const auto *FooVal = 3087 dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl)); 3088 ASSERT_THAT(FooVal, NotNull()); 3089 3090 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3091 ASSERT_THAT(BarDecl, NotNull()); 3092 3093 const auto *BarVal = 3094 dyn_cast_or_null<NegationValue>(Env.getValue(*BarDecl)); 3095 ASSERT_THAT(BarVal, NotNull()); 3096 3097 EXPECT_EQ(&BarVal->getSubVal(), FooVal); 3098 }); 3099 } 3100 3101 TEST(TransferTest, BuiltinExpect) { 3102 std::string Code = R"( 3103 void target(long Foo) { 3104 long Bar = __builtin_expect(Foo, true); 3105 /*[[p]]*/ 3106 } 3107 )"; 3108 runDataflow( 3109 Code, 3110 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3111 ASTContext &ASTCtx) { 3112 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3113 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3114 3115 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3116 ASSERT_THAT(FooDecl, NotNull()); 3117 3118 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3119 ASSERT_THAT(BarDecl, NotNull()); 3120 3121 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3122 }); 3123 } 3124 3125 // `__builtin_expect` takes and returns a `long` argument, so other types 3126 // involve casts. This verifies that we identify the input and output in that 3127 // case. 3128 TEST(TransferTest, BuiltinExpectBoolArg) { 3129 std::string Code = R"( 3130 void target(bool Foo) { 3131 bool Bar = __builtin_expect(Foo, true); 3132 /*[[p]]*/ 3133 } 3134 )"; 3135 runDataflow( 3136 Code, 3137 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3138 ASTContext &ASTCtx) { 3139 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3140 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3141 3142 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3143 ASSERT_THAT(FooDecl, NotNull()); 3144 3145 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3146 ASSERT_THAT(BarDecl, NotNull()); 3147 3148 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3149 }); 3150 } 3151 3152 TEST(TransferTest, BuiltinUnreachable) { 3153 std::string Code = R"( 3154 void target(bool Foo) { 3155 bool Bar = false; 3156 if (Foo) 3157 Bar = Foo; 3158 else 3159 __builtin_unreachable(); 3160 (void)0; 3161 /*[[p]]*/ 3162 } 3163 )"; 3164 runDataflow( 3165 Code, 3166 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3167 ASTContext &ASTCtx) { 3168 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3169 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3170 3171 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3172 ASSERT_THAT(FooDecl, NotNull()); 3173 3174 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3175 ASSERT_THAT(BarDecl, NotNull()); 3176 3177 // `__builtin_unreachable` promises that the code is 3178 // unreachable, so the compiler treats the "then" branch as the 3179 // only possible predecessor of this statement. 3180 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3181 }); 3182 } 3183 3184 TEST(TransferTest, BuiltinTrap) { 3185 std::string Code = R"( 3186 void target(bool Foo) { 3187 bool Bar = false; 3188 if (Foo) 3189 Bar = Foo; 3190 else 3191 __builtin_trap(); 3192 (void)0; 3193 /*[[p]]*/ 3194 } 3195 )"; 3196 runDataflow( 3197 Code, 3198 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3199 ASTContext &ASTCtx) { 3200 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3201 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3202 3203 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3204 ASSERT_THAT(FooDecl, NotNull()); 3205 3206 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3207 ASSERT_THAT(BarDecl, NotNull()); 3208 3209 // `__builtin_trap` ensures program termination, so only the 3210 // "then" branch is a predecessor of this statement. 3211 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3212 }); 3213 } 3214 3215 TEST(TransferTest, BuiltinDebugTrap) { 3216 std::string Code = R"( 3217 void target(bool Foo) { 3218 bool Bar = false; 3219 if (Foo) 3220 Bar = Foo; 3221 else 3222 __builtin_debugtrap(); 3223 (void)0; 3224 /*[[p]]*/ 3225 } 3226 )"; 3227 runDataflow( 3228 Code, 3229 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3230 ASTContext &ASTCtx) { 3231 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3232 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3233 3234 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3235 ASSERT_THAT(FooDecl, NotNull()); 3236 3237 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3238 ASSERT_THAT(BarDecl, NotNull()); 3239 3240 // `__builtin_debugtrap` doesn't ensure program termination. 3241 EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3242 }); 3243 } 3244 3245 TEST(TransferTest, StaticIntSingleVarDecl) { 3246 std::string Code = R"( 3247 void target() { 3248 static int Foo; 3249 // [[p]] 3250 } 3251 )"; 3252 runDataflow( 3253 Code, 3254 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3255 ASTContext &ASTCtx) { 3256 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3257 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3258 3259 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3260 ASSERT_THAT(FooDecl, NotNull()); 3261 3262 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 3263 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3264 3265 const Value *FooVal = Env.getValue(*FooLoc); 3266 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3267 }); 3268 } 3269 3270 TEST(TransferTest, StaticIntGroupVarDecl) { 3271 std::string Code = R"( 3272 void target() { 3273 static int Foo, Bar; 3274 (void)0; 3275 // [[p]] 3276 } 3277 )"; 3278 runDataflow( 3279 Code, 3280 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3281 ASTContext &ASTCtx) { 3282 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3283 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3284 3285 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3286 ASSERT_THAT(FooDecl, NotNull()); 3287 3288 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3289 ASSERT_THAT(BarDecl, NotNull()); 3290 3291 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 3292 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3293 3294 const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl); 3295 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 3296 3297 const Value *FooVal = Env.getValue(*FooLoc); 3298 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3299 3300 const Value *BarVal = Env.getValue(*BarLoc); 3301 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 3302 3303 EXPECT_NE(FooVal, BarVal); 3304 }); 3305 } 3306 3307 TEST(TransferTest, GlobalIntVarDecl) { 3308 std::string Code = R"( 3309 static int Foo; 3310 3311 void target() { 3312 int Bar = Foo; 3313 int Baz = Foo; 3314 // [[p]] 3315 } 3316 )"; 3317 runDataflow( 3318 Code, 3319 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3320 ASTContext &ASTCtx) { 3321 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3322 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3323 3324 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3325 ASSERT_THAT(BarDecl, NotNull()); 3326 3327 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3328 ASSERT_THAT(BazDecl, NotNull()); 3329 3330 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3331 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3332 EXPECT_EQ(BarVal, BazVal); 3333 }); 3334 } 3335 3336 TEST(TransferTest, StaticMemberIntVarDecl) { 3337 std::string Code = R"( 3338 struct A { 3339 static int Foo; 3340 }; 3341 3342 void target(A a) { 3343 int Bar = a.Foo; 3344 int Baz = a.Foo; 3345 // [[p]] 3346 } 3347 )"; 3348 runDataflow( 3349 Code, 3350 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3351 ASTContext &ASTCtx) { 3352 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3353 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3354 3355 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3356 ASSERT_THAT(BarDecl, NotNull()); 3357 3358 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3359 ASSERT_THAT(BazDecl, NotNull()); 3360 3361 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3362 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3363 EXPECT_EQ(BarVal, BazVal); 3364 }); 3365 } 3366 3367 TEST(TransferTest, StaticMemberRefVarDecl) { 3368 std::string Code = R"( 3369 struct A { 3370 static int &Foo; 3371 }; 3372 3373 void target(A a) { 3374 int Bar = a.Foo; 3375 int Baz = a.Foo; 3376 // [[p]] 3377 } 3378 )"; 3379 runDataflow( 3380 Code, 3381 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3382 ASTContext &ASTCtx) { 3383 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3384 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3385 3386 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3387 ASSERT_THAT(BarDecl, NotNull()); 3388 3389 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3390 ASSERT_THAT(BazDecl, NotNull()); 3391 3392 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3393 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3394 EXPECT_EQ(BarVal, BazVal); 3395 }); 3396 } 3397 3398 TEST(TransferTest, AssignMemberBeforeCopy) { 3399 std::string Code = R"( 3400 struct A { 3401 int Foo; 3402 }; 3403 3404 void target() { 3405 A A1; 3406 A A2; 3407 int Bar; 3408 A1.Foo = Bar; 3409 A2 = A1; 3410 // [[p]] 3411 } 3412 )"; 3413 runDataflow( 3414 Code, 3415 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3416 ASTContext &ASTCtx) { 3417 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3418 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3419 3420 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3421 ASSERT_THAT(FooDecl, NotNull()); 3422 3423 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3424 ASSERT_THAT(BarDecl, NotNull()); 3425 3426 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); 3427 ASSERT_THAT(A1Decl, NotNull()); 3428 3429 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); 3430 ASSERT_THAT(A2Decl, NotNull()); 3431 3432 const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3433 3434 const auto *A2Val = cast<StructValue>(Env.getValue(*A2Decl)); 3435 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal); 3436 }); 3437 } 3438 3439 TEST(TransferTest, BooleanEquality) { 3440 std::string Code = R"( 3441 void target(bool Bar) { 3442 bool Foo = true; 3443 if (Bar == Foo) { 3444 (void)0; 3445 /*[[p-then]]*/ 3446 } else { 3447 (void)0; 3448 /*[[p-else]]*/ 3449 } 3450 } 3451 )"; 3452 runDataflow( 3453 Code, 3454 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3455 ASTContext &ASTCtx) { 3456 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else")); 3457 const Environment &EnvThen = 3458 getEnvironmentAtAnnotation(Results, "p-then"); 3459 const Environment &EnvElse = 3460 getEnvironmentAtAnnotation(Results, "p-else"); 3461 3462 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3463 ASSERT_THAT(BarDecl, NotNull()); 3464 3465 auto &BarValThen = *cast<BoolValue>(EnvThen.getValue(*BarDecl)); 3466 EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen)); 3467 3468 auto &BarValElse = *cast<BoolValue>(EnvElse.getValue(*BarDecl)); 3469 EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse)); 3470 }); 3471 } 3472 3473 TEST(TransferTest, BooleanInequality) { 3474 std::string Code = R"( 3475 void target(bool Bar) { 3476 bool Foo = true; 3477 if (Bar != Foo) { 3478 (void)0; 3479 /*[[p-then]]*/ 3480 } else { 3481 (void)0; 3482 /*[[p-else]]*/ 3483 } 3484 } 3485 )"; 3486 runDataflow( 3487 Code, 3488 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3489 ASTContext &ASTCtx) { 3490 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else")); 3491 const Environment &EnvThen = 3492 getEnvironmentAtAnnotation(Results, "p-then"); 3493 const Environment &EnvElse = 3494 getEnvironmentAtAnnotation(Results, "p-else"); 3495 3496 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3497 ASSERT_THAT(BarDecl, NotNull()); 3498 3499 auto &BarValThen = *cast<BoolValue>(EnvThen.getValue(*BarDecl)); 3500 EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen)); 3501 3502 auto &BarValElse = *cast<BoolValue>(EnvElse.getValue(*BarDecl)); 3503 EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse)); 3504 }); 3505 } 3506 3507 TEST(TransferTest, IntegerLiteralEquality) { 3508 std::string Code = R"( 3509 void target() { 3510 bool equal = (42 == 42); 3511 // [[p]] 3512 } 3513 )"; 3514 runDataflow( 3515 Code, 3516 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3517 ASTContext &ASTCtx) { 3518 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3519 3520 auto &Equal = getValueForDecl<BoolValue>(ASTCtx, Env, "equal"); 3521 EXPECT_TRUE(Env.flowConditionImplies(Equal)); 3522 }); 3523 } 3524 3525 TEST(TransferTest, CorrelatedBranches) { 3526 std::string Code = R"( 3527 void target(bool B, bool C) { 3528 if (B) { 3529 return; 3530 } 3531 (void)0; 3532 /*[[p0]]*/ 3533 if (C) { 3534 B = true; 3535 /*[[p1]]*/ 3536 } 3537 if (B) { 3538 (void)0; 3539 /*[[p2]]*/ 3540 } 3541 } 3542 )"; 3543 runDataflow( 3544 Code, 3545 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3546 ASTContext &ASTCtx) { 3547 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2")); 3548 3549 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3550 ASSERT_THAT(CDecl, NotNull()); 3551 3552 { 3553 const Environment &Env = getEnvironmentAtAnnotation(Results, "p0"); 3554 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3555 ASSERT_THAT(BDecl, NotNull()); 3556 auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl)); 3557 3558 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal))); 3559 } 3560 3561 { 3562 const Environment &Env = getEnvironmentAtAnnotation(Results, "p1"); 3563 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl)); 3564 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3565 } 3566 3567 { 3568 const Environment &Env = getEnvironmentAtAnnotation(Results, "p2"); 3569 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl)); 3570 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3571 } 3572 }); 3573 } 3574 3575 TEST(TransferTest, LoopWithAssignmentConverges) { 3576 std::string Code = R"( 3577 bool foo(); 3578 3579 void target() { 3580 do { 3581 bool Bar = foo(); 3582 if (Bar) break; 3583 (void)Bar; 3584 /*[[p]]*/ 3585 } while (true); 3586 } 3587 )"; 3588 // The key property that we are verifying is implicit in `runDataflow` -- 3589 // namely, that the analysis succeeds, rather than hitting the maximum number 3590 // of iterations. 3591 runDataflow( 3592 Code, 3593 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3594 ASTContext &ASTCtx) { 3595 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3596 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3597 3598 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3599 ASSERT_THAT(BarDecl, NotNull()); 3600 3601 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 3602 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3603 }); 3604 } 3605 3606 TEST(TransferTest, LoopWithStagedAssignments) { 3607 std::string Code = R"( 3608 bool foo(); 3609 3610 void target() { 3611 bool Bar = false; 3612 bool Err = false; 3613 while (foo()) { 3614 if (Bar) 3615 Err = true; 3616 Bar = true; 3617 /*[[p]]*/ 3618 } 3619 } 3620 )"; 3621 runDataflow( 3622 Code, 3623 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3624 ASTContext &ASTCtx) { 3625 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3626 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3627 3628 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3629 ASSERT_THAT(BarDecl, NotNull()); 3630 const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err"); 3631 ASSERT_THAT(ErrDecl, NotNull()); 3632 3633 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 3634 auto &ErrVal = *cast<BoolValue>(Env.getValue(*ErrDecl)); 3635 EXPECT_TRUE(Env.flowConditionImplies(BarVal)); 3636 // An unsound analysis, for example only evaluating the loop once, can 3637 // conclude that `Err` is false. So, we test that this conclusion is not 3638 // reached. 3639 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(ErrVal))); 3640 }); 3641 } 3642 3643 TEST(TransferTest, LoopWithReferenceAssignmentConverges) { 3644 std::string Code = R"( 3645 bool &foo(); 3646 3647 void target() { 3648 do { 3649 bool& Bar = foo(); 3650 if (Bar) break; 3651 (void)Bar; 3652 /*[[p]]*/ 3653 } while (true); 3654 } 3655 )"; 3656 // The key property that we are verifying is that the analysis succeeds, 3657 // rather than hitting the maximum number of iterations. 3658 runDataflow( 3659 Code, 3660 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3661 ASTContext &ASTCtx) { 3662 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3663 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3664 3665 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3666 ASSERT_THAT(BarDecl, NotNull()); 3667 3668 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 3669 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3670 }); 3671 } 3672 3673 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) { 3674 std::string Code = R"( 3675 struct Lookup { 3676 int x; 3677 }; 3678 3679 void target(Lookup val, bool b) { 3680 const Lookup* l = nullptr; 3681 while (b) { 3682 l = &val; 3683 /*[[p-inner]]*/ 3684 } 3685 (void)0; 3686 /*[[p-outer]]*/ 3687 } 3688 )"; 3689 // The key property that we are verifying is implicit in `runDataflow` -- 3690 // namely, that the analysis succeeds, rather than hitting the maximum number 3691 // of iterations. 3692 runDataflow( 3693 Code, 3694 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3695 ASTContext &ASTCtx) { 3696 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer")); 3697 const Environment &InnerEnv = 3698 getEnvironmentAtAnnotation(Results, "p-inner"); 3699 const Environment &OuterEnv = 3700 getEnvironmentAtAnnotation(Results, "p-outer"); 3701 3702 const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val"); 3703 ASSERT_THAT(ValDecl, NotNull()); 3704 3705 const ValueDecl *LDecl = findValueDecl(ASTCtx, "l"); 3706 ASSERT_THAT(LDecl, NotNull()); 3707 3708 // Inner. 3709 auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl)); 3710 ASSERT_THAT(LVal, NotNull()); 3711 3712 EXPECT_EQ(&LVal->getPointeeLoc(), 3713 InnerEnv.getStorageLocation(*ValDecl)); 3714 3715 // Outer. 3716 LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl)); 3717 ASSERT_THAT(LVal, NotNull()); 3718 3719 // The loop body may not have been executed, so we should not conclude 3720 // that `l` points to `val`. 3721 EXPECT_NE(&LVal->getPointeeLoc(), 3722 OuterEnv.getStorageLocation(*ValDecl)); 3723 }); 3724 } 3725 3726 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { 3727 std::string Code = R"( 3728 union Union { 3729 int A; 3730 float B; 3731 }; 3732 3733 void foo() { 3734 Union A; 3735 Union B; 3736 A = B; 3737 } 3738 )"; 3739 // This is a crash regression test when calling the transfer function on a 3740 // `CXXThisExpr` that refers to a union. 3741 runDataflow( 3742 Code, 3743 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &, 3744 ASTContext &) {}, 3745 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator="); 3746 } 3747 3748 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) { 3749 std::string Code = R"( 3750 struct A { 3751 int Foo; 3752 int Bar; 3753 }; 3754 3755 void target() { 3756 int Qux; 3757 A Baz; 3758 Baz.Foo = Qux; 3759 auto &FooRef = Baz.Foo; 3760 auto &BarRef = Baz.Bar; 3761 auto &[BoundFooRef, BoundBarRef] = Baz; 3762 // [[p]] 3763 } 3764 )"; 3765 runDataflow( 3766 Code, 3767 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3768 ASTContext &ASTCtx) { 3769 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3770 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3771 3772 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3773 ASSERT_THAT(FooRefDecl, NotNull()); 3774 3775 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3776 ASSERT_THAT(BarRefDecl, NotNull()); 3777 3778 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3779 ASSERT_THAT(QuxDecl, NotNull()); 3780 3781 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3782 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3783 3784 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3785 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3786 3787 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 3788 ASSERT_THAT(FooRefLoc, NotNull()); 3789 3790 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 3791 ASSERT_THAT(BarRefLoc, NotNull()); 3792 3793 const Value *QuxVal = Env.getValue(*QuxDecl); 3794 ASSERT_THAT(QuxVal, NotNull()); 3795 3796 const StorageLocation *BoundFooRefLoc = 3797 Env.getStorageLocation(*BoundFooRefDecl); 3798 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3799 3800 const StorageLocation *BoundBarRefLoc = 3801 Env.getStorageLocation(*BoundBarRefDecl); 3802 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3803 3804 EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal); 3805 }); 3806 } 3807 3808 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) { 3809 std::string Code = R"( 3810 struct A { 3811 int &Foo; 3812 int &Bar; 3813 }; 3814 3815 void target(A Baz) { 3816 int Qux; 3817 Baz.Foo = Qux; 3818 auto &FooRef = Baz.Foo; 3819 auto &BarRef = Baz.Bar; 3820 auto &[BoundFooRef, BoundBarRef] = Baz; 3821 // [[p]] 3822 } 3823 )"; 3824 runDataflow( 3825 Code, 3826 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3827 ASTContext &ASTCtx) { 3828 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3829 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3830 3831 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3832 ASSERT_THAT(FooRefDecl, NotNull()); 3833 3834 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3835 ASSERT_THAT(BarRefDecl, NotNull()); 3836 3837 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3838 ASSERT_THAT(QuxDecl, NotNull()); 3839 3840 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3841 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3842 3843 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3844 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3845 3846 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 3847 ASSERT_THAT(FooRefLoc, NotNull()); 3848 3849 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 3850 ASSERT_THAT(BarRefLoc, NotNull()); 3851 3852 const Value *QuxVal = Env.getValue(*QuxDecl); 3853 ASSERT_THAT(QuxVal, NotNull()); 3854 3855 const StorageLocation *BoundFooRefLoc = 3856 Env.getStorageLocation(*BoundFooRefDecl); 3857 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3858 3859 const StorageLocation *BoundBarRefLoc = 3860 Env.getStorageLocation(*BoundBarRefDecl); 3861 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3862 3863 EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal); 3864 }); 3865 } 3866 3867 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) { 3868 std::string Code = R"( 3869 struct A { 3870 int Foo; 3871 int Bar; 3872 }; 3873 3874 void target() { 3875 int Qux; 3876 A Baz; 3877 Baz.Foo = Qux; 3878 auto &FooRef = Baz.Foo; 3879 auto &BarRef = Baz.Bar; 3880 auto [BoundFoo, BoundBar] = Baz; 3881 // [[p]] 3882 } 3883 )"; 3884 runDataflow( 3885 Code, 3886 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3887 ASTContext &ASTCtx) { 3888 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3889 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3890 3891 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3892 ASSERT_THAT(FooRefDecl, NotNull()); 3893 3894 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3895 ASSERT_THAT(BarRefDecl, NotNull()); 3896 3897 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 3898 ASSERT_THAT(BoundFooDecl, NotNull()); 3899 3900 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 3901 ASSERT_THAT(BoundBarDecl, NotNull()); 3902 3903 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3904 ASSERT_THAT(QuxDecl, NotNull()); 3905 3906 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 3907 ASSERT_THAT(FooRefLoc, NotNull()); 3908 3909 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 3910 ASSERT_THAT(BarRefLoc, NotNull()); 3911 3912 const Value *QuxVal = Env.getValue(*QuxDecl); 3913 ASSERT_THAT(QuxVal, NotNull()); 3914 3915 const StorageLocation *BoundFooLoc = 3916 Env.getStorageLocation(*BoundFooDecl); 3917 EXPECT_NE(BoundFooLoc, FooRefLoc); 3918 3919 const StorageLocation *BoundBarLoc = 3920 Env.getStorageLocation(*BoundBarDecl); 3921 EXPECT_NE(BoundBarLoc, BarRefLoc); 3922 3923 EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal); 3924 }); 3925 } 3926 3927 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) { 3928 std::string Code = R"( 3929 namespace std { 3930 using size_t = int; 3931 template <class> struct tuple_size; 3932 template <std::size_t, class> struct tuple_element; 3933 template <class...> class tuple; 3934 3935 namespace { 3936 template <class T, T v> 3937 struct size_helper { static const T value = v; }; 3938 } // namespace 3939 3940 template <class... T> 3941 struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {}; 3942 3943 template <std::size_t I, class... T> 3944 struct tuple_element<I, tuple<T...>> { 3945 using type = __type_pack_element<I, T...>; 3946 }; 3947 3948 template <class...> class tuple {}; 3949 3950 template <std::size_t I, class... T> 3951 typename tuple_element<I, tuple<T...>>::type get(tuple<T...>); 3952 } // namespace std 3953 3954 std::tuple<bool, int> makeTuple(); 3955 3956 void target(bool B) { 3957 auto [BoundFoo, BoundBar] = makeTuple(); 3958 bool Baz; 3959 // Include if-then-else to test interaction of `BindingDecl` with join. 3960 if (B) { 3961 Baz = BoundFoo; 3962 (void)BoundBar; 3963 // [[p1]] 3964 } else { 3965 Baz = BoundFoo; 3966 } 3967 (void)0; 3968 // [[p2]] 3969 } 3970 )"; 3971 runDataflow( 3972 Code, 3973 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3974 ASTContext &ASTCtx) { 3975 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 3976 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 3977 3978 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 3979 ASSERT_THAT(BoundFooDecl, NotNull()); 3980 3981 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 3982 ASSERT_THAT(BoundBarDecl, NotNull()); 3983 3984 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3985 ASSERT_THAT(BazDecl, NotNull()); 3986 3987 // BindingDecls always map to references -- either lvalue or rvalue, so 3988 // we still need to skip here. 3989 const Value *BoundFooValue = Env1.getValue(*BoundFooDecl); 3990 ASSERT_THAT(BoundFooValue, NotNull()); 3991 EXPECT_TRUE(isa<BoolValue>(BoundFooValue)); 3992 3993 const Value *BoundBarValue = Env1.getValue(*BoundBarDecl); 3994 ASSERT_THAT(BoundBarValue, NotNull()); 3995 EXPECT_TRUE(isa<IntegerValue>(BoundBarValue)); 3996 3997 // Test that a `DeclRefExpr` to a `BindingDecl` works as expected. 3998 EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue); 3999 4000 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 4001 4002 // Test that `BoundFooDecl` retains the value we expect, after the join. 4003 BoundFooValue = Env2.getValue(*BoundFooDecl); 4004 EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue); 4005 }); 4006 } 4007 4008 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) { 4009 std::string Code = R"( 4010 namespace std { 4011 using size_t = int; 4012 template <class> struct tuple_size; 4013 template <std::size_t, class> struct tuple_element; 4014 template <class...> class tuple; 4015 4016 namespace { 4017 template <class T, T v> 4018 struct size_helper { static const T value = v; }; 4019 } // namespace 4020 4021 template <class... T> 4022 struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {}; 4023 4024 template <std::size_t I, class... T> 4025 struct tuple_element<I, tuple<T...>> { 4026 using type = __type_pack_element<I, T...>; 4027 }; 4028 4029 template <class...> class tuple {}; 4030 4031 template <std::size_t I, class... T> 4032 typename tuple_element<I, tuple<T...>>::type get(tuple<T...>); 4033 } // namespace std 4034 4035 std::tuple<bool, int> &getTuple(); 4036 4037 void target(bool B) { 4038 auto &[BoundFoo, BoundBar] = getTuple(); 4039 bool Baz; 4040 // Include if-then-else to test interaction of `BindingDecl` with join. 4041 if (B) { 4042 Baz = BoundFoo; 4043 (void)BoundBar; 4044 // [[p1]] 4045 } else { 4046 Baz = BoundFoo; 4047 } 4048 (void)0; 4049 // [[p2]] 4050 } 4051 )"; 4052 runDataflow( 4053 Code, 4054 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4055 ASTContext &ASTCtx) { 4056 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 4057 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 4058 4059 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 4060 ASSERT_THAT(BoundFooDecl, NotNull()); 4061 4062 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 4063 ASSERT_THAT(BoundBarDecl, NotNull()); 4064 4065 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4066 ASSERT_THAT(BazDecl, NotNull()); 4067 4068 const Value *BoundFooValue = Env1.getValue(*BoundFooDecl); 4069 ASSERT_THAT(BoundFooValue, NotNull()); 4070 EXPECT_TRUE(isa<BoolValue>(BoundFooValue)); 4071 4072 const Value *BoundBarValue = Env1.getValue(*BoundBarDecl); 4073 ASSERT_THAT(BoundBarValue, NotNull()); 4074 EXPECT_TRUE(isa<IntegerValue>(BoundBarValue)); 4075 4076 // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type) 4077 // works as expected. We don't test aliasing properties of the 4078 // reference, because we don't model `std::get` and so have no way to 4079 // equate separate references into the tuple. 4080 EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue); 4081 4082 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 4083 4084 // Test that `BoundFooDecl` retains the value we expect, after the join. 4085 BoundFooValue = Env2.getValue(*BoundFooDecl); 4086 EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue); 4087 }); 4088 } 4089 4090 TEST(TransferTest, BinaryOperatorComma) { 4091 std::string Code = R"( 4092 void target(int Foo, int Bar) { 4093 int &Baz = (Foo, Bar); 4094 // [[p]] 4095 } 4096 )"; 4097 runDataflow( 4098 Code, 4099 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4100 ASTContext &ASTCtx) { 4101 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4102 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4103 4104 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4105 ASSERT_THAT(BarDecl, NotNull()); 4106 4107 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4108 ASSERT_THAT(BazDecl, NotNull()); 4109 4110 const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl); 4111 ASSERT_THAT(BarLoc, NotNull()); 4112 4113 const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl); 4114 EXPECT_EQ(BazLoc, BarLoc); 4115 }); 4116 } 4117 4118 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) { 4119 std::string Code = R"( 4120 void target(bool Foo) { 4121 if (Foo) { 4122 (void)0; 4123 // [[if_then]] 4124 } else { 4125 (void)0; 4126 // [[if_else]] 4127 } 4128 } 4129 )"; 4130 runDataflow( 4131 Code, 4132 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4133 ASTContext &ASTCtx) { 4134 ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else")); 4135 const Environment &ThenEnv = 4136 getEnvironmentAtAnnotation(Results, "if_then"); 4137 const Environment &ElseEnv = 4138 getEnvironmentAtAnnotation(Results, "if_else"); 4139 4140 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4141 ASSERT_THAT(FooDecl, NotNull()); 4142 4143 BoolValue &ThenFooVal = *cast<BoolValue>(ThenEnv.getValue(*FooDecl)); 4144 EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal)); 4145 4146 BoolValue &ElseFooVal = *cast<BoolValue>(ElseEnv.getValue(*FooDecl)); 4147 EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal))); 4148 }); 4149 } 4150 4151 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) { 4152 std::string Code = R"( 4153 void target(bool Foo) { 4154 while (Foo) { 4155 (void)0; 4156 // [[loop_body]] 4157 } 4158 (void)0; 4159 // [[after_loop]] 4160 } 4161 )"; 4162 runDataflow( 4163 Code, 4164 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4165 ASTContext &ASTCtx) { 4166 ASSERT_THAT(Results.keys(), 4167 UnorderedElementsAre("loop_body", "after_loop")); 4168 const Environment &LoopBodyEnv = 4169 getEnvironmentAtAnnotation(Results, "loop_body"); 4170 const Environment &AfterLoopEnv = 4171 getEnvironmentAtAnnotation(Results, "after_loop"); 4172 4173 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4174 ASSERT_THAT(FooDecl, NotNull()); 4175 4176 BoolValue &LoopBodyFooVal = 4177 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl)); 4178 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4179 4180 BoolValue &AfterLoopFooVal = 4181 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl)); 4182 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4183 AfterLoopEnv.makeNot(AfterLoopFooVal))); 4184 }); 4185 } 4186 4187 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) { 4188 std::string Code = R"( 4189 void target(bool Foo) { 4190 bool Bar = true; 4191 do { 4192 (void)0; 4193 // [[loop_body]] 4194 Bar = false; 4195 } while (Foo); 4196 (void)0; 4197 // [[after_loop]] 4198 } 4199 )"; 4200 runDataflow( 4201 Code, 4202 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4203 ASTContext &ASTCtx) { 4204 ASSERT_THAT(Results.keys(), 4205 UnorderedElementsAre("loop_body", "after_loop")); 4206 const Environment &LoopBodyEnv = 4207 getEnvironmentAtAnnotation(Results, "loop_body"); 4208 const Environment &AfterLoopEnv = 4209 getEnvironmentAtAnnotation(Results, "after_loop"); 4210 4211 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4212 ASSERT_THAT(FooDecl, NotNull()); 4213 4214 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4215 ASSERT_THAT(BarDecl, NotNull()); 4216 4217 BoolValue &LoopBodyFooVal = 4218 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl)); 4219 BoolValue &LoopBodyBarVal = 4220 *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl)); 4221 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies( 4222 LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal))); 4223 4224 BoolValue &AfterLoopFooVal = 4225 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl)); 4226 BoolValue &AfterLoopBarVal = 4227 *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl)); 4228 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4229 AfterLoopEnv.makeNot(AfterLoopFooVal))); 4230 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4231 AfterLoopEnv.makeNot(AfterLoopBarVal))); 4232 }); 4233 } 4234 4235 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) { 4236 std::string Code = R"( 4237 void target(bool Foo) { 4238 for (; Foo;) { 4239 (void)0; 4240 // [[loop_body]] 4241 } 4242 (void)0; 4243 // [[after_loop]] 4244 } 4245 )"; 4246 runDataflow( 4247 Code, 4248 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4249 ASTContext &ASTCtx) { 4250 ASSERT_THAT(Results.keys(), 4251 UnorderedElementsAre("loop_body", "after_loop")); 4252 const Environment &LoopBodyEnv = 4253 getEnvironmentAtAnnotation(Results, "loop_body"); 4254 const Environment &AfterLoopEnv = 4255 getEnvironmentAtAnnotation(Results, "after_loop"); 4256 4257 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4258 ASSERT_THAT(FooDecl, NotNull()); 4259 4260 BoolValue &LoopBodyFooVal = 4261 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl)); 4262 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4263 4264 BoolValue &AfterLoopFooVal = 4265 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl)); 4266 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4267 AfterLoopEnv.makeNot(AfterLoopFooVal))); 4268 }); 4269 } 4270 4271 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) { 4272 std::string Code = R"( 4273 void target(bool Foo) { 4274 for (;;) { 4275 (void)0; 4276 // [[loop_body]] 4277 } 4278 } 4279 )"; 4280 runDataflow( 4281 Code, 4282 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4283 ASTContext &ASTCtx) { 4284 ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body")); 4285 const Environment &LoopBodyEnv = 4286 getEnvironmentAtAnnotation(Results, "loop_body"); 4287 4288 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4289 ASSERT_THAT(FooDecl, NotNull()); 4290 4291 BoolValue &LoopBodyFooVal = 4292 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl)); 4293 EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4294 }); 4295 } 4296 4297 TEST(TransferTest, ContextSensitiveOptionDisabled) { 4298 std::string Code = R"( 4299 bool GiveBool(); 4300 void SetBool(bool &Var) { Var = true; } 4301 4302 void target() { 4303 bool Foo = GiveBool(); 4304 SetBool(Foo); 4305 // [[p]] 4306 } 4307 )"; 4308 runDataflow( 4309 Code, 4310 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4311 ASTContext &ASTCtx) { 4312 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4313 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4314 4315 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4316 ASSERT_THAT(FooDecl, NotNull()); 4317 4318 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4319 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4320 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4321 }, 4322 {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}}); 4323 } 4324 4325 TEST(TransferTest, ContextSensitiveReturnReference) { 4326 std::string Code = R"( 4327 class S {}; 4328 S& target(bool b, S &s) { 4329 return s; 4330 // [[p]] 4331 } 4332 )"; 4333 runDataflow( 4334 Code, 4335 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4336 ASTContext &ASTCtx) { 4337 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4338 4339 const ValueDecl *SDecl = findValueDecl(ASTCtx, "s"); 4340 ASSERT_THAT(SDecl, NotNull()); 4341 4342 auto *SLoc = Env.getStorageLocation(*SDecl); 4343 ASSERT_THAT(SLoc, NotNull()); 4344 4345 ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc)); 4346 }, 4347 {BuiltinOptions{ContextSensitiveOptions{}}}); 4348 } 4349 4350 // This test is a regression test, based on a real crash. 4351 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) { 4352 std::string Code = R"( 4353 class S {}; 4354 S& target(bool b, S &s) { 4355 return b ? s : s; 4356 // [[p]] 4357 } 4358 )"; 4359 runDataflow( 4360 Code, 4361 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4362 ASTContext &ASTCtx) { 4363 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4364 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4365 4366 const ValueDecl *SDecl = findValueDecl(ASTCtx, "s"); 4367 ASSERT_THAT(SDecl, NotNull()); 4368 4369 auto *SLoc = Env.getStorageLocation(*SDecl); 4370 ASSERT_THAT(SLoc, NotNull()); 4371 EXPECT_THAT(Env.getValue(*SLoc), NotNull()); 4372 4373 auto *Loc = Env.getReturnStorageLocation(); 4374 ASSERT_THAT(Loc, NotNull()); 4375 EXPECT_THAT(Env.getValue(*Loc), NotNull()); 4376 4377 // TODO: We would really like to make this stronger assertion, but that 4378 // doesn't work because we don't propagate values correctly through 4379 // the conditional operator yet. 4380 // ASSERT_THAT(Loc, Eq(SLoc)); 4381 }, 4382 {BuiltinOptions{ContextSensitiveOptions{}}}); 4383 } 4384 4385 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) { 4386 std::string Code = R"( 4387 class S {}; 4388 S &callee(bool b, S &s1_parm, S &s2_parm) { 4389 if (b) 4390 return s1_parm; 4391 else 4392 return s2_parm; 4393 } 4394 void target(bool b) { 4395 S s1; 4396 S s2; 4397 S &return_s1 = s1; 4398 S &return_s2 = s2; 4399 S &return_dont_know = callee(b, s1, s2); 4400 // [[p]] 4401 } 4402 )"; 4403 runDataflow( 4404 Code, 4405 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4406 ASTContext &ASTCtx) { 4407 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4408 4409 const ValueDecl *S1 = findValueDecl(ASTCtx, "s1"); 4410 ASSERT_THAT(S1, NotNull()); 4411 const ValueDecl *S2 = findValueDecl(ASTCtx, "s2"); 4412 ASSERT_THAT(S2, NotNull()); 4413 const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1"); 4414 ASSERT_THAT(ReturnS1, NotNull()); 4415 const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2"); 4416 ASSERT_THAT(ReturnS2, NotNull()); 4417 const ValueDecl *ReturnDontKnow = 4418 findValueDecl(ASTCtx, "return_dont_know"); 4419 ASSERT_THAT(ReturnDontKnow, NotNull()); 4420 4421 StorageLocation *S1Loc = Env.getStorageLocation(*S1); 4422 StorageLocation *S2Loc = Env.getStorageLocation(*S2); 4423 4424 EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc)); 4425 EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc)); 4426 4427 // In the case where we don't have a consistent storage location for 4428 // the return value, the framework creates a new storage location, which 4429 // should be different from the storage locations of `s1` and `s2`. 4430 EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc)); 4431 EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc)); 4432 }, 4433 {BuiltinOptions{ContextSensitiveOptions{}}}); 4434 } 4435 4436 TEST(TransferTest, ContextSensitiveDepthZero) { 4437 std::string Code = R"( 4438 bool GiveBool(); 4439 void SetBool(bool &Var) { Var = true; } 4440 4441 void target() { 4442 bool Foo = GiveBool(); 4443 SetBool(Foo); 4444 // [[p]] 4445 } 4446 )"; 4447 runDataflow( 4448 Code, 4449 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4450 ASTContext &ASTCtx) { 4451 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4452 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4453 4454 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4455 ASSERT_THAT(FooDecl, NotNull()); 4456 4457 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4458 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4459 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4460 }, 4461 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}}); 4462 } 4463 4464 TEST(TransferTest, ContextSensitiveSetTrue) { 4465 std::string Code = R"( 4466 bool GiveBool(); 4467 void SetBool(bool &Var) { Var = true; } 4468 4469 void target() { 4470 bool Foo = GiveBool(); 4471 SetBool(Foo); 4472 // [[p]] 4473 } 4474 )"; 4475 runDataflow( 4476 Code, 4477 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4478 ASTContext &ASTCtx) { 4479 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4480 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4481 4482 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4483 ASSERT_THAT(FooDecl, NotNull()); 4484 4485 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4486 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4487 }, 4488 {BuiltinOptions{ContextSensitiveOptions{}}}); 4489 } 4490 4491 TEST(TransferTest, ContextSensitiveSetFalse) { 4492 std::string Code = R"( 4493 bool GiveBool(); 4494 void SetBool(bool &Var) { Var = false; } 4495 4496 void target() { 4497 bool Foo = GiveBool(); 4498 SetBool(Foo); 4499 // [[p]] 4500 } 4501 )"; 4502 runDataflow( 4503 Code, 4504 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4505 ASTContext &ASTCtx) { 4506 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4507 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4508 4509 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4510 ASSERT_THAT(FooDecl, NotNull()); 4511 4512 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4513 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4514 }, 4515 {BuiltinOptions{ContextSensitiveOptions{}}}); 4516 } 4517 4518 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) { 4519 std::string Code = R"( 4520 bool GiveBool(); 4521 void SetBool(bool &Var, bool Val) { Var = Val; } 4522 4523 void target() { 4524 bool Foo = GiveBool(); 4525 bool Bar = GiveBool(); 4526 SetBool(Foo, true); 4527 SetBool(Bar, false); 4528 // [[p]] 4529 } 4530 )"; 4531 runDataflow( 4532 Code, 4533 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4534 ASTContext &ASTCtx) { 4535 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4536 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4537 4538 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4539 ASSERT_THAT(FooDecl, NotNull()); 4540 4541 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4542 ASSERT_THAT(BarDecl, NotNull()); 4543 4544 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4545 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4546 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4547 4548 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 4549 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4550 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4551 }, 4552 {BuiltinOptions{ContextSensitiveOptions{}}}); 4553 } 4554 4555 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) { 4556 std::string Code = R"( 4557 bool GiveBool(); 4558 void SetBool1(bool &Var) { Var = true; } 4559 void SetBool2(bool &Var) { SetBool1(Var); } 4560 4561 void target() { 4562 bool Foo = GiveBool(); 4563 SetBool2(Foo); 4564 // [[p]] 4565 } 4566 )"; 4567 runDataflow( 4568 Code, 4569 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4570 ASTContext &ASTCtx) { 4571 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4572 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4573 4574 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4575 ASSERT_THAT(FooDecl, NotNull()); 4576 4577 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4578 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4579 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4580 }, 4581 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}}); 4582 } 4583 4584 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) { 4585 std::string Code = R"( 4586 bool GiveBool(); 4587 void SetBool1(bool &Var) { Var = true; } 4588 void SetBool2(bool &Var) { SetBool1(Var); } 4589 4590 void target() { 4591 bool Foo = GiveBool(); 4592 SetBool2(Foo); 4593 // [[p]] 4594 } 4595 )"; 4596 runDataflow( 4597 Code, 4598 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4599 ASTContext &ASTCtx) { 4600 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4601 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4602 4603 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4604 ASSERT_THAT(FooDecl, NotNull()); 4605 4606 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4607 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4608 }, 4609 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}}); 4610 } 4611 4612 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) { 4613 std::string Code = R"( 4614 bool GiveBool(); 4615 void SetBool1(bool &Var) { Var = true; } 4616 void SetBool2(bool &Var) { SetBool1(Var); } 4617 void SetBool3(bool &Var) { SetBool2(Var); } 4618 4619 void target() { 4620 bool Foo = GiveBool(); 4621 SetBool3(Foo); 4622 // [[p]] 4623 } 4624 )"; 4625 runDataflow( 4626 Code, 4627 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4628 ASTContext &ASTCtx) { 4629 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4630 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4631 4632 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4633 ASSERT_THAT(FooDecl, NotNull()); 4634 4635 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4636 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4637 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4638 }, 4639 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}}); 4640 } 4641 4642 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) { 4643 std::string Code = R"( 4644 bool GiveBool(); 4645 void SetBool1(bool &Var) { Var = true; } 4646 void SetBool2(bool &Var) { SetBool1(Var); } 4647 void SetBool3(bool &Var) { SetBool2(Var); } 4648 4649 void target() { 4650 bool Foo = GiveBool(); 4651 SetBool3(Foo); 4652 // [[p]] 4653 } 4654 )"; 4655 runDataflow( 4656 Code, 4657 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4658 ASTContext &ASTCtx) { 4659 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4660 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4661 4662 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4663 ASSERT_THAT(FooDecl, NotNull()); 4664 4665 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4666 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4667 }, 4668 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}}); 4669 } 4670 4671 TEST(TransferTest, ContextSensitiveMutualRecursion) { 4672 std::string Code = R"( 4673 bool Pong(bool X, bool Y); 4674 4675 bool Ping(bool X, bool Y) { 4676 if (X) { 4677 return Y; 4678 } else { 4679 return Pong(!X, Y); 4680 } 4681 } 4682 4683 bool Pong(bool X, bool Y) { 4684 if (Y) { 4685 return X; 4686 } else { 4687 return Ping(X, !Y); 4688 } 4689 } 4690 4691 void target() { 4692 bool Foo = Ping(false, false); 4693 // [[p]] 4694 } 4695 )"; 4696 runDataflow( 4697 Code, 4698 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4699 ASTContext &ASTCtx) { 4700 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4701 // The analysis doesn't crash... 4702 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4703 4704 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4705 ASSERT_THAT(FooDecl, NotNull()); 4706 4707 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4708 // ... but it also can't prove anything here. 4709 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4710 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4711 }, 4712 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}}); 4713 } 4714 4715 TEST(TransferTest, ContextSensitiveSetMultipleLines) { 4716 std::string Code = R"( 4717 void SetBools(bool &Var1, bool &Var2) { 4718 Var1 = true; 4719 Var2 = false; 4720 } 4721 4722 void target() { 4723 bool Foo = false; 4724 bool Bar = true; 4725 SetBools(Foo, Bar); 4726 // [[p]] 4727 } 4728 )"; 4729 runDataflow( 4730 Code, 4731 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4732 ASTContext &ASTCtx) { 4733 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4734 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4735 4736 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4737 ASSERT_THAT(FooDecl, NotNull()); 4738 4739 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4740 ASSERT_THAT(BarDecl, NotNull()); 4741 4742 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4743 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4744 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4745 4746 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 4747 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4748 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4749 }, 4750 {BuiltinOptions{ContextSensitiveOptions{}}}); 4751 } 4752 4753 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) { 4754 std::string Code = R"( 4755 void IfCond(bool Cond, bool &Then, bool &Else) { 4756 if (Cond) { 4757 Then = true; 4758 } else { 4759 Else = true; 4760 } 4761 } 4762 4763 void target() { 4764 bool Foo = false; 4765 bool Bar = false; 4766 bool Baz = false; 4767 IfCond(Foo, Bar, Baz); 4768 // [[p]] 4769 } 4770 )"; 4771 runDataflow( 4772 Code, 4773 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4774 ASTContext &ASTCtx) { 4775 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4776 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4777 4778 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4779 ASSERT_THAT(BarDecl, NotNull()); 4780 4781 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4782 ASSERT_THAT(BazDecl, NotNull()); 4783 4784 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 4785 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4786 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4787 4788 auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl)); 4789 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 4790 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal))); 4791 }, 4792 {BuiltinOptions{ContextSensitiveOptions{}}}); 4793 } 4794 4795 TEST(TransferTest, ContextSensitiveReturnVoid) { 4796 std::string Code = R"( 4797 void Noop() { return; } 4798 4799 void target() { 4800 Noop(); 4801 // [[p]] 4802 } 4803 )"; 4804 runDataflow( 4805 Code, 4806 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4807 ASTContext &ASTCtx) { 4808 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4809 // This just tests that the analysis doesn't crash. 4810 }, 4811 {BuiltinOptions{ContextSensitiveOptions{}}}); 4812 } 4813 4814 TEST(TransferTest, ContextSensitiveReturnTrue) { 4815 std::string Code = R"( 4816 bool GiveBool() { return true; } 4817 4818 void target() { 4819 bool Foo = GiveBool(); 4820 // [[p]] 4821 } 4822 )"; 4823 runDataflow( 4824 Code, 4825 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4826 ASTContext &ASTCtx) { 4827 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4828 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4829 4830 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4831 ASSERT_THAT(FooDecl, NotNull()); 4832 4833 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4834 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4835 }, 4836 {BuiltinOptions{ContextSensitiveOptions{}}}); 4837 } 4838 4839 TEST(TransferTest, ContextSensitiveReturnFalse) { 4840 std::string Code = R"( 4841 bool GiveBool() { return false; } 4842 4843 void target() { 4844 bool Foo = GiveBool(); 4845 // [[p]] 4846 } 4847 )"; 4848 runDataflow( 4849 Code, 4850 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4851 ASTContext &ASTCtx) { 4852 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4853 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4854 4855 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4856 ASSERT_THAT(FooDecl, NotNull()); 4857 4858 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4859 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4860 }, 4861 {BuiltinOptions{ContextSensitiveOptions{}}}); 4862 } 4863 4864 TEST(TransferTest, ContextSensitiveReturnArg) { 4865 std::string Code = R"( 4866 bool GiveBool(); 4867 bool GiveBack(bool Arg) { return Arg; } 4868 4869 void target() { 4870 bool Foo = GiveBool(); 4871 bool Bar = GiveBack(Foo); 4872 bool Baz = Foo == Bar; 4873 // [[p]] 4874 } 4875 )"; 4876 runDataflow( 4877 Code, 4878 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4879 ASTContext &ASTCtx) { 4880 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4881 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4882 4883 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4884 ASSERT_THAT(BazDecl, NotNull()); 4885 4886 auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl)); 4887 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 4888 }, 4889 {BuiltinOptions{ContextSensitiveOptions{}}}); 4890 } 4891 4892 TEST(TransferTest, ContextSensitiveReturnInt) { 4893 std::string Code = R"( 4894 int identity(int x) { return x; } 4895 4896 void target() { 4897 int y = identity(42); 4898 // [[p]] 4899 } 4900 )"; 4901 runDataflow( 4902 Code, 4903 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4904 ASTContext &ASTCtx) { 4905 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4906 // This just tests that the analysis doesn't crash. 4907 }, 4908 {BuiltinOptions{ContextSensitiveOptions{}}}); 4909 } 4910 4911 TEST(TransferTest, ContextSensitiveMethodLiteral) { 4912 std::string Code = R"( 4913 class MyClass { 4914 public: 4915 bool giveBool() { return true; } 4916 }; 4917 4918 void target() { 4919 MyClass MyObj; 4920 bool Foo = MyObj.giveBool(); 4921 // [[p]] 4922 } 4923 )"; 4924 runDataflow( 4925 Code, 4926 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4927 ASTContext &ASTCtx) { 4928 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4929 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4930 4931 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4932 ASSERT_THAT(FooDecl, NotNull()); 4933 4934 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4935 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4936 }, 4937 {BuiltinOptions{ContextSensitiveOptions{}}}); 4938 } 4939 4940 TEST(TransferTest, ContextSensitiveMethodGetter) { 4941 std::string Code = R"( 4942 class MyClass { 4943 public: 4944 bool getField() { return Field; } 4945 4946 bool Field; 4947 }; 4948 4949 void target() { 4950 MyClass MyObj; 4951 MyObj.Field = true; 4952 bool Foo = MyObj.getField(); 4953 // [[p]] 4954 } 4955 )"; 4956 runDataflow( 4957 Code, 4958 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4959 ASTContext &ASTCtx) { 4960 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4961 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4962 4963 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4964 ASSERT_THAT(FooDecl, NotNull()); 4965 4966 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4967 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4968 }, 4969 {BuiltinOptions{ContextSensitiveOptions{}}}); 4970 } 4971 4972 TEST(TransferTest, ContextSensitiveMethodSetter) { 4973 std::string Code = R"( 4974 class MyClass { 4975 public: 4976 void setField(bool Val) { Field = Val; } 4977 4978 bool Field; 4979 }; 4980 4981 void target() { 4982 MyClass MyObj; 4983 MyObj.setField(true); 4984 bool Foo = MyObj.Field; 4985 // [[p]] 4986 } 4987 )"; 4988 runDataflow( 4989 Code, 4990 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4991 ASTContext &ASTCtx) { 4992 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4993 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4994 4995 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4996 ASSERT_THAT(FooDecl, NotNull()); 4997 4998 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4999 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5000 }, 5001 {BuiltinOptions{ContextSensitiveOptions{}}}); 5002 } 5003 5004 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) { 5005 std::string Code = R"( 5006 class MyClass { 5007 public: 5008 bool getField() { return Field; } 5009 void setField(bool Val) { Field = Val; } 5010 5011 private: 5012 bool Field; 5013 }; 5014 5015 void target() { 5016 MyClass MyObj; 5017 MyObj.setField(true); 5018 bool Foo = MyObj.getField(); 5019 // [[p]] 5020 } 5021 )"; 5022 runDataflow( 5023 Code, 5024 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5025 ASTContext &ASTCtx) { 5026 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5027 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5028 5029 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5030 ASSERT_THAT(FooDecl, NotNull()); 5031 5032 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5033 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5034 }, 5035 {BuiltinOptions{ContextSensitiveOptions{}}}); 5036 } 5037 5038 5039 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) { 5040 std::string Code = R"( 5041 class MyClass { 5042 public: 5043 void Inner() { MyField = true; } 5044 void Outer() { Inner(); } 5045 5046 bool MyField; 5047 }; 5048 5049 void target() { 5050 MyClass MyObj; 5051 MyObj.Outer(); 5052 bool Foo = MyObj.MyField; 5053 // [[p]] 5054 } 5055 )"; 5056 runDataflow( 5057 Code, 5058 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5059 ASTContext &ASTCtx) { 5060 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5061 ; 5062 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5063 5064 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5065 ASSERT_THAT(FooDecl, NotNull()); 5066 5067 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5068 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5069 }, 5070 {BuiltinOptions{ContextSensitiveOptions{}}}); 5071 } 5072 5073 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) { 5074 std::string Code = R"( 5075 class MyClass { 5076 public: 5077 bool Inner() { return MyField; } 5078 bool Outer() { return Inner(); } 5079 5080 bool MyField; 5081 }; 5082 5083 void target() { 5084 MyClass MyObj; 5085 MyObj.MyField = true; 5086 bool Foo = MyObj.Outer(); 5087 // [[p]] 5088 } 5089 )"; 5090 runDataflow( 5091 Code, 5092 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5093 ASTContext &ASTCtx) { 5094 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5095 ; 5096 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5097 5098 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5099 ASSERT_THAT(FooDecl, NotNull()); 5100 5101 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5102 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5103 }, 5104 {BuiltinOptions{ContextSensitiveOptions{}}}); 5105 } 5106 5107 TEST(TransferTest, ContextSensitiveConstructorBody) { 5108 std::string Code = R"( 5109 class MyClass { 5110 public: 5111 MyClass() { MyField = true; } 5112 5113 bool MyField; 5114 }; 5115 5116 void target() { 5117 MyClass MyObj; 5118 bool Foo = MyObj.MyField; 5119 // [[p]] 5120 } 5121 )"; 5122 runDataflow( 5123 Code, 5124 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5125 ASTContext &ASTCtx) { 5126 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5127 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5128 5129 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5130 ASSERT_THAT(FooDecl, NotNull()); 5131 5132 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5133 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5134 }, 5135 {BuiltinOptions{ContextSensitiveOptions{}}}); 5136 } 5137 5138 TEST(TransferTest, ContextSensitiveConstructorInitializer) { 5139 std::string Code = R"( 5140 class MyClass { 5141 public: 5142 MyClass() : MyField(true) {} 5143 5144 bool MyField; 5145 }; 5146 5147 void target() { 5148 MyClass MyObj; 5149 bool Foo = MyObj.MyField; 5150 // [[p]] 5151 } 5152 )"; 5153 runDataflow( 5154 Code, 5155 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5156 ASTContext &ASTCtx) { 5157 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5158 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5159 5160 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5161 ASSERT_THAT(FooDecl, NotNull()); 5162 5163 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5164 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5165 }, 5166 {BuiltinOptions{ContextSensitiveOptions{}}}); 5167 } 5168 5169 TEST(TransferTest, ContextSensitiveConstructorDefault) { 5170 std::string Code = R"( 5171 class MyClass { 5172 public: 5173 MyClass() = default; 5174 5175 bool MyField = true; 5176 }; 5177 5178 void target() { 5179 MyClass MyObj; 5180 bool Foo = MyObj.MyField; 5181 // [[p]] 5182 } 5183 )"; 5184 runDataflow( 5185 Code, 5186 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5187 ASTContext &ASTCtx) { 5188 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5189 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5190 5191 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5192 ASSERT_THAT(FooDecl, NotNull()); 5193 5194 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5195 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5196 }, 5197 {BuiltinOptions{ContextSensitiveOptions{}}}); 5198 } 5199 5200 TEST(TransferTest, UnnamedBitfieldInitializer) { 5201 std::string Code = R"( 5202 struct B {}; 5203 struct A { 5204 unsigned a; 5205 unsigned : 4; 5206 unsigned c; 5207 B b; 5208 }; 5209 void target() { 5210 A a = {}; 5211 A test = a; 5212 (void)test.c; 5213 } 5214 )"; 5215 runDataflow( 5216 Code, 5217 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5218 ASTContext &ASTCtx) { 5219 // This doesn't need a body because this test was crashing the framework 5220 // before handling correctly Unnamed bitfields in `InitListExpr`. 5221 }); 5222 } 5223 5224 // Repro for a crash that used to occur with chained short-circuiting logical 5225 // operators. 5226 TEST(TransferTest, ChainedLogicalOps) { 5227 std::string Code = R"( 5228 bool target() { 5229 bool b = true || false || false || false; 5230 // [[p]] 5231 return b; 5232 } 5233 )"; 5234 runDataflow( 5235 Code, 5236 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5237 ASTContext &ASTCtx) { 5238 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5239 auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b"); 5240 EXPECT_TRUE(Env.flowConditionImplies(B)); 5241 }); 5242 } 5243 5244 // Repro for a crash that used to occur when we call a `noreturn` function 5245 // within one of the operands of a `&&` or `||` operator. 5246 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) { 5247 std::string Code = R"( 5248 __attribute__((noreturn)) int doesnt_return(); 5249 bool some_condition(); 5250 void target(bool b1, bool b2) { 5251 // Neither of these should crash. In addition, if we don't terminate the 5252 // program, we know that the operators need to trigger the short-circuit 5253 // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr` 5254 // will be true. 5255 bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0; 5256 bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0; 5257 5258 // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the 5259 // entire expression unreachable. So we know that in both of the following 5260 // cases, if `target()` terminates, the `else` branch was taken. 5261 bool NoreturnOnLhsMakesAndUnreachable = false; 5262 if (some_condition()) 5263 doesnt_return() > 0 && some_condition(); 5264 else 5265 NoreturnOnLhsMakesAndUnreachable = true; 5266 5267 bool NoreturnOnLhsMakesOrUnreachable = false; 5268 if (some_condition()) 5269 doesnt_return() > 0 || some_condition(); 5270 else 5271 NoreturnOnLhsMakesOrUnreachable = true; 5272 5273 // [[p]] 5274 } 5275 )"; 5276 runDataflow( 5277 Code, 5278 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5279 ASTContext &ASTCtx) { 5280 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5281 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5282 5283 // Check that [[p]] is reachable with a non-false flow condition. 5284 EXPECT_FALSE(Env.flowConditionImplies(Env.getBoolLiteralValue(false))); 5285 5286 auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1"); 5287 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(B1))); 5288 5289 auto &NoreturnOnRhsOfAnd = 5290 getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd"); 5291 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(NoreturnOnRhsOfAnd))); 5292 5293 auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2"); 5294 EXPECT_TRUE(Env.flowConditionImplies(B2)); 5295 5296 auto &NoreturnOnRhsOfOr = 5297 getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr"); 5298 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnRhsOfOr)); 5299 5300 auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>( 5301 ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable"); 5302 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesAndUnreachable)); 5303 5304 auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>( 5305 ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable"); 5306 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesOrUnreachable)); 5307 }); 5308 } 5309 5310 TEST(TransferTest, NewExpressions) { 5311 std::string Code = R"( 5312 void target() { 5313 int *p = new int(42); 5314 // [[after_new]] 5315 } 5316 )"; 5317 runDataflow( 5318 Code, 5319 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5320 ASTContext &ASTCtx) { 5321 const Environment &Env = 5322 getEnvironmentAtAnnotation(Results, "after_new"); 5323 5324 auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p"); 5325 5326 EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull()); 5327 }); 5328 } 5329 5330 TEST(TransferTest, NewExpressions_Structs) { 5331 std::string Code = R"( 5332 struct Inner { 5333 int InnerField; 5334 }; 5335 5336 struct Outer { 5337 Inner OuterField; 5338 }; 5339 5340 void target() { 5341 Outer *p = new Outer; 5342 // Access the fields to make sure the analysis actually generates children 5343 // for them in the `AggregateStorageLoc` and `StructValue`. 5344 p->OuterField.InnerField; 5345 // [[after_new]] 5346 } 5347 )"; 5348 runDataflow( 5349 Code, 5350 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5351 ASTContext &ASTCtx) { 5352 const Environment &Env = 5353 getEnvironmentAtAnnotation(Results, "after_new"); 5354 5355 const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField"); 5356 const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField"); 5357 5358 auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p"); 5359 5360 auto &OuterLoc = cast<AggregateStorageLocation>(P.getPointeeLoc()); 5361 auto &OuterFieldLoc = 5362 cast<AggregateStorageLocation>(OuterLoc.getChild(*OuterField)); 5363 auto &InnerFieldLoc = OuterFieldLoc.getChild(*InnerField); 5364 5365 // Values for the struct and all fields exist after the new. 5366 EXPECT_THAT(Env.getValue(OuterLoc), NotNull()); 5367 EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull()); 5368 EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull()); 5369 }); 5370 } 5371 5372 TEST(TransferTest, FunctionToPointerDecayHasValue) { 5373 std::string Code = R"( 5374 struct A { static void static_member_func(); }; 5375 void target() { 5376 // To check that we're treating function-to-pointer decay correctly, 5377 // create two pointers, then verify they refer to the same storage 5378 // location. 5379 // We need to do the test this way because even if an initializer (in this 5380 // case, the function-to-pointer decay) does not create a value, we still 5381 // create a value for the variable. 5382 void (*non_member_p1)() = target; 5383 void (*non_member_p2)() = target; 5384 5385 // Do the same thing but for a static member function. 5386 void (*member_p1)() = A::static_member_func; 5387 void (*member_p2)() = A::static_member_func; 5388 // [[p]] 5389 } 5390 )"; 5391 runDataflow( 5392 Code, 5393 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5394 ASTContext &ASTCtx) { 5395 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5396 5397 auto &NonMemberP1 = 5398 getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1"); 5399 auto &NonMemberP2 = 5400 getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2"); 5401 EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc()); 5402 5403 auto &MemberP1 = 5404 getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1"); 5405 auto &MemberP2 = 5406 getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2"); 5407 EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc()); 5408 }); 5409 } 5410 5411 // Check that the pointer that a builtin function decays to is associated with 5412 // a value. 5413 TEST(TransferTest, BuiltinFunctionModeled) { 5414 std::string Code = R"( 5415 void target() { 5416 __builtin_expect(0, 0); 5417 // [[p]] 5418 } 5419 )"; 5420 runDataflow( 5421 Code, 5422 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5423 ASTContext &ASTCtx) { 5424 using ast_matchers::selectFirst; 5425 using ast_matchers::match; 5426 using ast_matchers::traverse; 5427 using ast_matchers::implicitCastExpr; 5428 using ast_matchers::hasCastKind; 5429 5430 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5431 5432 auto *ImplicitCast = selectFirst<ImplicitCastExpr>( 5433 "implicit_cast", 5434 match(traverse(TK_AsIs, 5435 implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr)) 5436 .bind("implicit_cast")), 5437 ASTCtx)); 5438 5439 ASSERT_THAT(ImplicitCast, NotNull()); 5440 EXPECT_THAT(Env.getValueStrict(*ImplicitCast), NotNull()); 5441 }); 5442 } 5443 5444 // Check that fields of anonymous records are modeled. 5445 TEST(TransferTest, AnonymousStruct) { 5446 std::string Code = R"( 5447 struct S { 5448 struct { 5449 bool b; 5450 }; 5451 }; 5452 void target() { 5453 S s; 5454 s.b = true; 5455 // [[p]] 5456 } 5457 )"; 5458 runDataflow( 5459 Code, 5460 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5461 ASTContext &ASTCtx) { 5462 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5463 const ValueDecl *SDecl = findValueDecl(ASTCtx, "s"); 5464 const ValueDecl *BDecl = findValueDecl(ASTCtx, "b"); 5465 const IndirectFieldDecl *IndirectField = 5466 findIndirectFieldDecl(ASTCtx, "b"); 5467 5468 auto *S = 5469 cast<AggregateStorageLocation>(Env.getStorageLocation(*SDecl)); 5470 auto &AnonStruct = cast<AggregateStorageLocation>( 5471 S->getChild(*cast<ValueDecl>(IndirectField->chain().front()))); 5472 5473 auto *B = cast<BoolValue>(Env.getValue(AnonStruct.getChild(*BDecl))); 5474 ASSERT_TRUE(Env.flowConditionImplies(*B)); 5475 }); 5476 } 5477 5478 TEST(TransferTest, AnonymousStructWithInitializer) { 5479 std::string Code = R"( 5480 struct target { 5481 target() { 5482 (void)0; 5483 // [[p]] 5484 } 5485 struct { 5486 bool b = true; 5487 }; 5488 }; 5489 )"; 5490 runDataflow( 5491 Code, 5492 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5493 ASTContext &ASTCtx) { 5494 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5495 const ValueDecl *BDecl = findValueDecl(ASTCtx, "b"); 5496 const IndirectFieldDecl *IndirectField = 5497 findIndirectFieldDecl(ASTCtx, "b"); 5498 5499 auto *ThisLoc = 5500 cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation()); 5501 auto &AnonStruct = cast<AggregateStorageLocation>(ThisLoc->getChild( 5502 *cast<ValueDecl>(IndirectField->chain().front()))); 5503 5504 auto *B = cast<BoolValue>(Env.getValue(AnonStruct.getChild(*BDecl))); 5505 ASSERT_TRUE(Env.flowConditionImplies(*B)); 5506 }); 5507 } 5508 5509 } // namespace 5510