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