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