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