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<ConjunctionValue>(Env.getValue(*BazDecl)); 3022 ASSERT_THAT(BazVal, NotNull()); 3023 EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal); 3024 3025 const auto *BazRightSubValVal = 3026 cast<DisjunctionValue>(&BazVal->getRightSubValue()); 3027 EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal); 3028 EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal); 3029 }); 3030 } 3031 3032 { 3033 std::string Code = R"( 3034 void target(bool Foo, bool Bar, bool Qux) { 3035 bool Baz = (Foo && Qux) || (Bar); 3036 // [[p]] 3037 } 3038 )"; 3039 runDataflow( 3040 Code, 3041 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3042 ASTContext &ASTCtx) { 3043 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3044 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3045 3046 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3047 ASSERT_THAT(FooDecl, NotNull()); 3048 3049 const auto *FooVal = 3050 dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl)); 3051 ASSERT_THAT(FooVal, NotNull()); 3052 3053 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3054 ASSERT_THAT(BarDecl, NotNull()); 3055 3056 const auto *BarVal = 3057 dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl)); 3058 ASSERT_THAT(BarVal, NotNull()); 3059 3060 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3061 ASSERT_THAT(QuxDecl, NotNull()); 3062 3063 const auto *QuxVal = 3064 dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl)); 3065 ASSERT_THAT(QuxVal, NotNull()); 3066 3067 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3068 ASSERT_THAT(BazDecl, NotNull()); 3069 3070 const auto *BazVal = 3071 dyn_cast_or_null<DisjunctionValue>(Env.getValue(*BazDecl)); 3072 ASSERT_THAT(BazVal, NotNull()); 3073 3074 const auto *BazLeftSubValVal = 3075 cast<ConjunctionValue>(&BazVal->getLeftSubValue()); 3076 EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal); 3077 EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal); 3078 3079 EXPECT_EQ(&BazVal->getRightSubValue(), BarVal); 3080 }); 3081 } 3082 3083 { 3084 std::string Code = R"( 3085 void target(bool A, bool B, bool C, bool D) { 3086 bool Foo = ((A && B) && C) && D; 3087 // [[p]] 3088 } 3089 )"; 3090 runDataflow( 3091 Code, 3092 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3093 ASTContext &ASTCtx) { 3094 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3095 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3096 3097 const ValueDecl *ADecl = findValueDecl(ASTCtx, "A"); 3098 ASSERT_THAT(ADecl, NotNull()); 3099 3100 const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl)); 3101 ASSERT_THAT(AVal, NotNull()); 3102 3103 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3104 ASSERT_THAT(BDecl, NotNull()); 3105 3106 const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl)); 3107 ASSERT_THAT(BVal, NotNull()); 3108 3109 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3110 ASSERT_THAT(CDecl, NotNull()); 3111 3112 const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl)); 3113 ASSERT_THAT(CVal, NotNull()); 3114 3115 const ValueDecl *DDecl = findValueDecl(ASTCtx, "D"); 3116 ASSERT_THAT(DDecl, NotNull()); 3117 3118 const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl)); 3119 ASSERT_THAT(DVal, NotNull()); 3120 3121 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3122 ASSERT_THAT(FooDecl, NotNull()); 3123 3124 const auto *FooVal = 3125 dyn_cast_or_null<ConjunctionValue>(Env.getValue(*FooDecl)); 3126 ASSERT_THAT(FooVal, NotNull()); 3127 3128 const auto &FooLeftSubVal = 3129 cast<ConjunctionValue>(FooVal->getLeftSubValue()); 3130 const auto &FooLeftLeftSubVal = 3131 cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue()); 3132 EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal); 3133 EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal); 3134 EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal); 3135 EXPECT_EQ(&FooVal->getRightSubValue(), DVal); 3136 }); 3137 } 3138 } 3139 3140 TEST(TransferTest, AssignFromBoolNegation) { 3141 std::string Code = R"( 3142 void target() { 3143 bool Foo = true; 3144 bool Bar = !(Foo); 3145 // [[p]] 3146 } 3147 )"; 3148 runDataflow( 3149 Code, 3150 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3151 ASTContext &ASTCtx) { 3152 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3153 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3154 3155 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3156 ASSERT_THAT(FooDecl, NotNull()); 3157 3158 const auto *FooVal = 3159 dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl)); 3160 ASSERT_THAT(FooVal, NotNull()); 3161 3162 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3163 ASSERT_THAT(BarDecl, NotNull()); 3164 3165 const auto *BarVal = 3166 dyn_cast_or_null<NegationValue>(Env.getValue(*BarDecl)); 3167 ASSERT_THAT(BarVal, NotNull()); 3168 3169 EXPECT_EQ(&BarVal->getSubVal(), FooVal); 3170 }); 3171 } 3172 3173 TEST(TransferTest, BuiltinExpect) { 3174 std::string Code = R"( 3175 void target(long Foo) { 3176 long Bar = __builtin_expect(Foo, true); 3177 /*[[p]]*/ 3178 } 3179 )"; 3180 runDataflow( 3181 Code, 3182 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3183 ASTContext &ASTCtx) { 3184 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3185 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3186 3187 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3188 ASSERT_THAT(FooDecl, NotNull()); 3189 3190 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3191 ASSERT_THAT(BarDecl, NotNull()); 3192 3193 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3194 }); 3195 } 3196 3197 // `__builtin_expect` takes and returns a `long` argument, so other types 3198 // involve casts. This verifies that we identify the input and output in that 3199 // case. 3200 TEST(TransferTest, BuiltinExpectBoolArg) { 3201 std::string Code = R"( 3202 void target(bool Foo) { 3203 bool Bar = __builtin_expect(Foo, true); 3204 /*[[p]]*/ 3205 } 3206 )"; 3207 runDataflow( 3208 Code, 3209 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3210 ASTContext &ASTCtx) { 3211 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3212 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3213 3214 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3215 ASSERT_THAT(FooDecl, NotNull()); 3216 3217 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3218 ASSERT_THAT(BarDecl, NotNull()); 3219 3220 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3221 }); 3222 } 3223 3224 TEST(TransferTest, BuiltinUnreachable) { 3225 std::string Code = R"( 3226 void target(bool Foo) { 3227 bool Bar = false; 3228 if (Foo) 3229 Bar = Foo; 3230 else 3231 __builtin_unreachable(); 3232 (void)0; 3233 /*[[p]]*/ 3234 } 3235 )"; 3236 runDataflow( 3237 Code, 3238 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3239 ASTContext &ASTCtx) { 3240 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3241 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3242 3243 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3244 ASSERT_THAT(FooDecl, NotNull()); 3245 3246 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3247 ASSERT_THAT(BarDecl, NotNull()); 3248 3249 // `__builtin_unreachable` promises that the code is 3250 // unreachable, so the compiler treats the "then" branch as the 3251 // only possible predecessor of this statement. 3252 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3253 }); 3254 } 3255 3256 TEST(TransferTest, BuiltinTrap) { 3257 std::string Code = R"( 3258 void target(bool Foo) { 3259 bool Bar = false; 3260 if (Foo) 3261 Bar = Foo; 3262 else 3263 __builtin_trap(); 3264 (void)0; 3265 /*[[p]]*/ 3266 } 3267 )"; 3268 runDataflow( 3269 Code, 3270 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3271 ASTContext &ASTCtx) { 3272 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3273 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3274 3275 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3276 ASSERT_THAT(FooDecl, NotNull()); 3277 3278 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3279 ASSERT_THAT(BarDecl, NotNull()); 3280 3281 // `__builtin_trap` ensures program termination, so only the 3282 // "then" branch is a predecessor of this statement. 3283 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3284 }); 3285 } 3286 3287 TEST(TransferTest, BuiltinDebugTrap) { 3288 std::string Code = R"( 3289 void target(bool Foo) { 3290 bool Bar = false; 3291 if (Foo) 3292 Bar = Foo; 3293 else 3294 __builtin_debugtrap(); 3295 (void)0; 3296 /*[[p]]*/ 3297 } 3298 )"; 3299 runDataflow( 3300 Code, 3301 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3302 ASTContext &ASTCtx) { 3303 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3304 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3305 3306 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3307 ASSERT_THAT(FooDecl, NotNull()); 3308 3309 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3310 ASSERT_THAT(BarDecl, NotNull()); 3311 3312 // `__builtin_debugtrap` doesn't ensure program termination. 3313 EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3314 }); 3315 } 3316 3317 TEST(TransferTest, StaticIntSingleVarDecl) { 3318 std::string Code = R"( 3319 void target() { 3320 static int Foo; 3321 // [[p]] 3322 } 3323 )"; 3324 runDataflow( 3325 Code, 3326 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3327 ASTContext &ASTCtx) { 3328 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3329 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3330 3331 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3332 ASSERT_THAT(FooDecl, NotNull()); 3333 3334 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 3335 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3336 3337 const Value *FooVal = Env.getValue(*FooLoc); 3338 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3339 }); 3340 } 3341 3342 TEST(TransferTest, StaticIntGroupVarDecl) { 3343 std::string Code = R"( 3344 void target() { 3345 static int Foo, Bar; 3346 (void)0; 3347 // [[p]] 3348 } 3349 )"; 3350 runDataflow( 3351 Code, 3352 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3353 ASTContext &ASTCtx) { 3354 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3355 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3356 3357 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3358 ASSERT_THAT(FooDecl, NotNull()); 3359 3360 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3361 ASSERT_THAT(BarDecl, NotNull()); 3362 3363 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 3364 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3365 3366 const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl); 3367 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 3368 3369 const Value *FooVal = Env.getValue(*FooLoc); 3370 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3371 3372 const Value *BarVal = Env.getValue(*BarLoc); 3373 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 3374 3375 EXPECT_NE(FooVal, BarVal); 3376 }); 3377 } 3378 3379 TEST(TransferTest, GlobalIntVarDecl) { 3380 std::string Code = R"( 3381 static int Foo; 3382 3383 void target() { 3384 int Bar = Foo; 3385 int Baz = Foo; 3386 // [[p]] 3387 } 3388 )"; 3389 runDataflow( 3390 Code, 3391 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3392 ASTContext &ASTCtx) { 3393 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3394 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3395 3396 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3397 ASSERT_THAT(BarDecl, NotNull()); 3398 3399 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3400 ASSERT_THAT(BazDecl, NotNull()); 3401 3402 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3403 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3404 EXPECT_EQ(BarVal, BazVal); 3405 }); 3406 } 3407 3408 TEST(TransferTest, StaticMemberIntVarDecl) { 3409 std::string Code = R"( 3410 struct A { 3411 static int Foo; 3412 }; 3413 3414 void target(A a) { 3415 int Bar = a.Foo; 3416 int Baz = a.Foo; 3417 // [[p]] 3418 } 3419 )"; 3420 runDataflow( 3421 Code, 3422 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3423 ASTContext &ASTCtx) { 3424 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3425 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3426 3427 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3428 ASSERT_THAT(BarDecl, NotNull()); 3429 3430 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3431 ASSERT_THAT(BazDecl, NotNull()); 3432 3433 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3434 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3435 EXPECT_EQ(BarVal, BazVal); 3436 }); 3437 } 3438 3439 TEST(TransferTest, StaticMemberRefVarDecl) { 3440 std::string Code = R"( 3441 struct A { 3442 static int &Foo; 3443 }; 3444 3445 void target(A a) { 3446 int Bar = a.Foo; 3447 int Baz = a.Foo; 3448 // [[p]] 3449 } 3450 )"; 3451 runDataflow( 3452 Code, 3453 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3454 ASTContext &ASTCtx) { 3455 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3456 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3457 3458 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3459 ASSERT_THAT(BarDecl, NotNull()); 3460 3461 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3462 ASSERT_THAT(BazDecl, NotNull()); 3463 3464 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3465 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3466 EXPECT_EQ(BarVal, BazVal); 3467 }); 3468 } 3469 3470 TEST(TransferTest, AssignMemberBeforeCopy) { 3471 std::string Code = R"( 3472 struct A { 3473 int Foo; 3474 }; 3475 3476 void target() { 3477 A A1; 3478 A A2; 3479 int Bar; 3480 A1.Foo = Bar; 3481 A2 = A1; 3482 // [[p]] 3483 } 3484 )"; 3485 runDataflow( 3486 Code, 3487 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3488 ASTContext &ASTCtx) { 3489 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3490 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3491 3492 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3493 ASSERT_THAT(FooDecl, NotNull()); 3494 3495 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3496 ASSERT_THAT(BarDecl, NotNull()); 3497 3498 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); 3499 ASSERT_THAT(A1Decl, NotNull()); 3500 3501 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); 3502 ASSERT_THAT(A2Decl, NotNull()); 3503 3504 const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3505 3506 const auto *A2Val = cast<StructValue>(Env.getValue(*A2Decl)); 3507 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal); 3508 }); 3509 } 3510 3511 TEST(TransferTest, BooleanEquality) { 3512 std::string Code = R"( 3513 void target(bool Bar) { 3514 bool Foo = true; 3515 if (Bar == Foo) { 3516 (void)0; 3517 /*[[p-then]]*/ 3518 } else { 3519 (void)0; 3520 /*[[p-else]]*/ 3521 } 3522 } 3523 )"; 3524 runDataflow( 3525 Code, 3526 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3527 ASTContext &ASTCtx) { 3528 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else")); 3529 const Environment &EnvThen = 3530 getEnvironmentAtAnnotation(Results, "p-then"); 3531 const Environment &EnvElse = 3532 getEnvironmentAtAnnotation(Results, "p-else"); 3533 3534 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3535 ASSERT_THAT(BarDecl, NotNull()); 3536 3537 auto &BarValThen = *cast<BoolValue>(EnvThen.getValue(*BarDecl)); 3538 EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen)); 3539 3540 auto &BarValElse = *cast<BoolValue>(EnvElse.getValue(*BarDecl)); 3541 EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse)); 3542 }); 3543 } 3544 3545 TEST(TransferTest, BooleanInequality) { 3546 std::string Code = R"( 3547 void target(bool Bar) { 3548 bool Foo = true; 3549 if (Bar != Foo) { 3550 (void)0; 3551 /*[[p-then]]*/ 3552 } else { 3553 (void)0; 3554 /*[[p-else]]*/ 3555 } 3556 } 3557 )"; 3558 runDataflow( 3559 Code, 3560 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3561 ASTContext &ASTCtx) { 3562 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else")); 3563 const Environment &EnvThen = 3564 getEnvironmentAtAnnotation(Results, "p-then"); 3565 const Environment &EnvElse = 3566 getEnvironmentAtAnnotation(Results, "p-else"); 3567 3568 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3569 ASSERT_THAT(BarDecl, NotNull()); 3570 3571 auto &BarValThen = *cast<BoolValue>(EnvThen.getValue(*BarDecl)); 3572 EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen)); 3573 3574 auto &BarValElse = *cast<BoolValue>(EnvElse.getValue(*BarDecl)); 3575 EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse)); 3576 }); 3577 } 3578 3579 TEST(TransferTest, IntegerLiteralEquality) { 3580 std::string Code = R"( 3581 void target() { 3582 bool equal = (42 == 42); 3583 // [[p]] 3584 } 3585 )"; 3586 runDataflow( 3587 Code, 3588 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3589 ASTContext &ASTCtx) { 3590 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3591 3592 auto &Equal = getValueForDecl<BoolValue>(ASTCtx, Env, "equal"); 3593 EXPECT_TRUE(Env.flowConditionImplies(Equal)); 3594 }); 3595 } 3596 3597 TEST(TransferTest, CorrelatedBranches) { 3598 std::string Code = R"( 3599 void target(bool B, bool C) { 3600 if (B) { 3601 return; 3602 } 3603 (void)0; 3604 /*[[p0]]*/ 3605 if (C) { 3606 B = true; 3607 /*[[p1]]*/ 3608 } 3609 if (B) { 3610 (void)0; 3611 /*[[p2]]*/ 3612 } 3613 } 3614 )"; 3615 runDataflow( 3616 Code, 3617 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3618 ASTContext &ASTCtx) { 3619 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2")); 3620 3621 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3622 ASSERT_THAT(CDecl, NotNull()); 3623 3624 { 3625 const Environment &Env = getEnvironmentAtAnnotation(Results, "p0"); 3626 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3627 ASSERT_THAT(BDecl, NotNull()); 3628 auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl)); 3629 3630 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal))); 3631 } 3632 3633 { 3634 const Environment &Env = getEnvironmentAtAnnotation(Results, "p1"); 3635 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl)); 3636 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3637 } 3638 3639 { 3640 const Environment &Env = getEnvironmentAtAnnotation(Results, "p2"); 3641 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl)); 3642 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3643 } 3644 }); 3645 } 3646 3647 TEST(TransferTest, LoopWithAssignmentConverges) { 3648 std::string Code = R"( 3649 bool foo(); 3650 3651 void target() { 3652 do { 3653 bool Bar = foo(); 3654 if (Bar) break; 3655 (void)Bar; 3656 /*[[p]]*/ 3657 } while (true); 3658 } 3659 )"; 3660 // The key property that we are verifying is implicit in `runDataflow` -- 3661 // namely, that the analysis succeeds, rather than hitting the maximum number 3662 // of iterations. 3663 runDataflow( 3664 Code, 3665 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3666 ASTContext &ASTCtx) { 3667 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3668 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3669 3670 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3671 ASSERT_THAT(BarDecl, NotNull()); 3672 3673 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 3674 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3675 }); 3676 } 3677 3678 TEST(TransferTest, LoopWithStagedAssignments) { 3679 std::string Code = R"( 3680 bool foo(); 3681 3682 void target() { 3683 bool Bar = false; 3684 bool Err = false; 3685 while (foo()) { 3686 if (Bar) 3687 Err = true; 3688 Bar = true; 3689 /*[[p]]*/ 3690 } 3691 } 3692 )"; 3693 runDataflow( 3694 Code, 3695 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3696 ASTContext &ASTCtx) { 3697 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3698 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3699 3700 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3701 ASSERT_THAT(BarDecl, NotNull()); 3702 const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err"); 3703 ASSERT_THAT(ErrDecl, NotNull()); 3704 3705 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 3706 auto &ErrVal = *cast<BoolValue>(Env.getValue(*ErrDecl)); 3707 EXPECT_TRUE(Env.flowConditionImplies(BarVal)); 3708 // An unsound analysis, for example only evaluating the loop once, can 3709 // conclude that `Err` is false. So, we test that this conclusion is not 3710 // reached. 3711 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(ErrVal))); 3712 }); 3713 } 3714 3715 TEST(TransferTest, LoopWithReferenceAssignmentConverges) { 3716 std::string Code = R"( 3717 bool &foo(); 3718 3719 void target() { 3720 do { 3721 bool& Bar = foo(); 3722 if (Bar) break; 3723 (void)Bar; 3724 /*[[p]]*/ 3725 } while (true); 3726 } 3727 )"; 3728 // The key property that we are verifying is that the analysis succeeds, 3729 // rather than hitting the maximum number of iterations. 3730 runDataflow( 3731 Code, 3732 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3733 ASTContext &ASTCtx) { 3734 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3735 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3736 3737 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3738 ASSERT_THAT(BarDecl, NotNull()); 3739 3740 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 3741 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3742 }); 3743 } 3744 3745 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) { 3746 std::string Code = R"( 3747 struct Lookup { 3748 int x; 3749 }; 3750 3751 void target(Lookup val, bool b) { 3752 const Lookup* l = nullptr; 3753 while (b) { 3754 l = &val; 3755 /*[[p-inner]]*/ 3756 } 3757 (void)0; 3758 /*[[p-outer]]*/ 3759 } 3760 )"; 3761 // The key property that we are verifying is implicit in `runDataflow` -- 3762 // namely, that the analysis succeeds, rather than hitting the maximum number 3763 // of iterations. 3764 runDataflow( 3765 Code, 3766 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3767 ASTContext &ASTCtx) { 3768 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer")); 3769 const Environment &InnerEnv = 3770 getEnvironmentAtAnnotation(Results, "p-inner"); 3771 const Environment &OuterEnv = 3772 getEnvironmentAtAnnotation(Results, "p-outer"); 3773 3774 const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val"); 3775 ASSERT_THAT(ValDecl, NotNull()); 3776 3777 const ValueDecl *LDecl = findValueDecl(ASTCtx, "l"); 3778 ASSERT_THAT(LDecl, NotNull()); 3779 3780 // Inner. 3781 auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl)); 3782 ASSERT_THAT(LVal, NotNull()); 3783 3784 EXPECT_EQ(&LVal->getPointeeLoc(), 3785 InnerEnv.getStorageLocation(*ValDecl)); 3786 3787 // Outer. 3788 LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl)); 3789 ASSERT_THAT(LVal, NotNull()); 3790 3791 // The loop body may not have been executed, so we should not conclude 3792 // that `l` points to `val`. 3793 EXPECT_NE(&LVal->getPointeeLoc(), 3794 OuterEnv.getStorageLocation(*ValDecl)); 3795 }); 3796 } 3797 3798 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { 3799 std::string Code = R"( 3800 union Union { 3801 int A; 3802 float B; 3803 }; 3804 3805 void foo() { 3806 Union A; 3807 Union B; 3808 A = B; 3809 } 3810 )"; 3811 // This is a crash regression test when calling the transfer function on a 3812 // `CXXThisExpr` that refers to a union. 3813 runDataflow( 3814 Code, 3815 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &, 3816 ASTContext &) {}, 3817 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator="); 3818 } 3819 3820 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) { 3821 std::string Code = R"( 3822 struct A { 3823 int Foo; 3824 int Bar; 3825 }; 3826 3827 void target() { 3828 int Qux; 3829 A Baz; 3830 Baz.Foo = Qux; 3831 auto &FooRef = Baz.Foo; 3832 auto &BarRef = Baz.Bar; 3833 auto &[BoundFooRef, BoundBarRef] = Baz; 3834 // [[p]] 3835 } 3836 )"; 3837 runDataflow( 3838 Code, 3839 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3840 ASTContext &ASTCtx) { 3841 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3842 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3843 3844 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3845 ASSERT_THAT(FooRefDecl, NotNull()); 3846 3847 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3848 ASSERT_THAT(BarRefDecl, NotNull()); 3849 3850 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3851 ASSERT_THAT(QuxDecl, NotNull()); 3852 3853 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3854 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3855 3856 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3857 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3858 3859 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 3860 ASSERT_THAT(FooRefLoc, NotNull()); 3861 3862 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 3863 ASSERT_THAT(BarRefLoc, NotNull()); 3864 3865 const Value *QuxVal = Env.getValue(*QuxDecl); 3866 ASSERT_THAT(QuxVal, NotNull()); 3867 3868 const StorageLocation *BoundFooRefLoc = 3869 Env.getStorageLocation(*BoundFooRefDecl); 3870 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3871 3872 const StorageLocation *BoundBarRefLoc = 3873 Env.getStorageLocation(*BoundBarRefDecl); 3874 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3875 3876 EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal); 3877 }); 3878 } 3879 3880 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) { 3881 std::string Code = R"( 3882 struct A { 3883 int &Foo; 3884 int &Bar; 3885 }; 3886 3887 void target(A Baz) { 3888 int Qux; 3889 Baz.Foo = Qux; 3890 auto &FooRef = Baz.Foo; 3891 auto &BarRef = Baz.Bar; 3892 auto &[BoundFooRef, BoundBarRef] = Baz; 3893 // [[p]] 3894 } 3895 )"; 3896 runDataflow( 3897 Code, 3898 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3899 ASTContext &ASTCtx) { 3900 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3901 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3902 3903 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3904 ASSERT_THAT(FooRefDecl, NotNull()); 3905 3906 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3907 ASSERT_THAT(BarRefDecl, NotNull()); 3908 3909 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3910 ASSERT_THAT(QuxDecl, NotNull()); 3911 3912 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3913 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3914 3915 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3916 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3917 3918 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 3919 ASSERT_THAT(FooRefLoc, NotNull()); 3920 3921 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 3922 ASSERT_THAT(BarRefLoc, NotNull()); 3923 3924 const Value *QuxVal = Env.getValue(*QuxDecl); 3925 ASSERT_THAT(QuxVal, NotNull()); 3926 3927 const StorageLocation *BoundFooRefLoc = 3928 Env.getStorageLocation(*BoundFooRefDecl); 3929 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3930 3931 const StorageLocation *BoundBarRefLoc = 3932 Env.getStorageLocation(*BoundBarRefDecl); 3933 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3934 3935 EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal); 3936 }); 3937 } 3938 3939 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) { 3940 std::string Code = R"( 3941 struct A { 3942 int Foo; 3943 int Bar; 3944 }; 3945 3946 void target() { 3947 int Qux; 3948 A Baz; 3949 Baz.Foo = Qux; 3950 auto &FooRef = Baz.Foo; 3951 auto &BarRef = Baz.Bar; 3952 auto [BoundFoo, BoundBar] = Baz; 3953 // [[p]] 3954 } 3955 )"; 3956 runDataflow( 3957 Code, 3958 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3959 ASTContext &ASTCtx) { 3960 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3961 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3962 3963 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3964 ASSERT_THAT(FooRefDecl, NotNull()); 3965 3966 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3967 ASSERT_THAT(BarRefDecl, NotNull()); 3968 3969 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 3970 ASSERT_THAT(BoundFooDecl, NotNull()); 3971 3972 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 3973 ASSERT_THAT(BoundBarDecl, NotNull()); 3974 3975 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3976 ASSERT_THAT(QuxDecl, NotNull()); 3977 3978 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 3979 ASSERT_THAT(FooRefLoc, NotNull()); 3980 3981 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 3982 ASSERT_THAT(BarRefLoc, NotNull()); 3983 3984 const Value *QuxVal = Env.getValue(*QuxDecl); 3985 ASSERT_THAT(QuxVal, NotNull()); 3986 3987 const StorageLocation *BoundFooLoc = 3988 Env.getStorageLocation(*BoundFooDecl); 3989 EXPECT_NE(BoundFooLoc, FooRefLoc); 3990 3991 const StorageLocation *BoundBarLoc = 3992 Env.getStorageLocation(*BoundBarDecl); 3993 EXPECT_NE(BoundBarLoc, BarRefLoc); 3994 3995 EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal); 3996 }); 3997 } 3998 3999 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) { 4000 std::string Code = R"( 4001 namespace std { 4002 using size_t = int; 4003 template <class> struct tuple_size; 4004 template <std::size_t, class> struct tuple_element; 4005 template <class...> class tuple; 4006 4007 namespace { 4008 template <class T, T v> 4009 struct size_helper { static const T value = v; }; 4010 } // namespace 4011 4012 template <class... T> 4013 struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {}; 4014 4015 template <std::size_t I, class... T> 4016 struct tuple_element<I, tuple<T...>> { 4017 using type = __type_pack_element<I, T...>; 4018 }; 4019 4020 template <class...> class tuple {}; 4021 4022 template <std::size_t I, class... T> 4023 typename tuple_element<I, tuple<T...>>::type get(tuple<T...>); 4024 } // namespace std 4025 4026 std::tuple<bool, int> makeTuple(); 4027 4028 void target(bool B) { 4029 auto [BoundFoo, BoundBar] = makeTuple(); 4030 bool Baz; 4031 // Include if-then-else to test interaction of `BindingDecl` with join. 4032 if (B) { 4033 Baz = BoundFoo; 4034 (void)BoundBar; 4035 // [[p1]] 4036 } else { 4037 Baz = BoundFoo; 4038 } 4039 (void)0; 4040 // [[p2]] 4041 } 4042 )"; 4043 runDataflow( 4044 Code, 4045 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4046 ASTContext &ASTCtx) { 4047 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 4048 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 4049 4050 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 4051 ASSERT_THAT(BoundFooDecl, NotNull()); 4052 4053 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 4054 ASSERT_THAT(BoundBarDecl, NotNull()); 4055 4056 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4057 ASSERT_THAT(BazDecl, NotNull()); 4058 4059 // BindingDecls always map to references -- either lvalue or rvalue, so 4060 // we still need to skip here. 4061 const Value *BoundFooValue = Env1.getValue(*BoundFooDecl); 4062 ASSERT_THAT(BoundFooValue, NotNull()); 4063 EXPECT_TRUE(isa<BoolValue>(BoundFooValue)); 4064 4065 const Value *BoundBarValue = Env1.getValue(*BoundBarDecl); 4066 ASSERT_THAT(BoundBarValue, NotNull()); 4067 EXPECT_TRUE(isa<IntegerValue>(BoundBarValue)); 4068 4069 // Test that a `DeclRefExpr` to a `BindingDecl` works as expected. 4070 EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue); 4071 4072 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 4073 4074 // Test that `BoundFooDecl` retains the value we expect, after the join. 4075 BoundFooValue = Env2.getValue(*BoundFooDecl); 4076 EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue); 4077 }); 4078 } 4079 4080 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) { 4081 std::string Code = R"( 4082 namespace std { 4083 using size_t = int; 4084 template <class> struct tuple_size; 4085 template <std::size_t, class> struct tuple_element; 4086 template <class...> class tuple; 4087 4088 namespace { 4089 template <class T, T v> 4090 struct size_helper { static const T value = v; }; 4091 } // namespace 4092 4093 template <class... T> 4094 struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {}; 4095 4096 template <std::size_t I, class... T> 4097 struct tuple_element<I, tuple<T...>> { 4098 using type = __type_pack_element<I, T...>; 4099 }; 4100 4101 template <class...> class tuple {}; 4102 4103 template <std::size_t I, class... T> 4104 typename tuple_element<I, tuple<T...>>::type get(tuple<T...>); 4105 } // namespace std 4106 4107 std::tuple<bool, int> &getTuple(); 4108 4109 void target(bool B) { 4110 auto &[BoundFoo, BoundBar] = getTuple(); 4111 bool Baz; 4112 // Include if-then-else to test interaction of `BindingDecl` with join. 4113 if (B) { 4114 Baz = BoundFoo; 4115 (void)BoundBar; 4116 // [[p1]] 4117 } else { 4118 Baz = BoundFoo; 4119 } 4120 (void)0; 4121 // [[p2]] 4122 } 4123 )"; 4124 runDataflow( 4125 Code, 4126 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4127 ASTContext &ASTCtx) { 4128 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 4129 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 4130 4131 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 4132 ASSERT_THAT(BoundFooDecl, NotNull()); 4133 4134 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 4135 ASSERT_THAT(BoundBarDecl, NotNull()); 4136 4137 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4138 ASSERT_THAT(BazDecl, NotNull()); 4139 4140 const Value *BoundFooValue = Env1.getValue(*BoundFooDecl); 4141 ASSERT_THAT(BoundFooValue, NotNull()); 4142 EXPECT_TRUE(isa<BoolValue>(BoundFooValue)); 4143 4144 const Value *BoundBarValue = Env1.getValue(*BoundBarDecl); 4145 ASSERT_THAT(BoundBarValue, NotNull()); 4146 EXPECT_TRUE(isa<IntegerValue>(BoundBarValue)); 4147 4148 // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type) 4149 // works as expected. We don't test aliasing properties of the 4150 // reference, because we don't model `std::get` and so have no way to 4151 // equate separate references into the tuple. 4152 EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue); 4153 4154 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 4155 4156 // Test that `BoundFooDecl` retains the value we expect, after the join. 4157 BoundFooValue = Env2.getValue(*BoundFooDecl); 4158 EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue); 4159 }); 4160 } 4161 4162 TEST(TransferTest, BinaryOperatorComma) { 4163 std::string Code = R"( 4164 void target(int Foo, int Bar) { 4165 int &Baz = (Foo, Bar); 4166 // [[p]] 4167 } 4168 )"; 4169 runDataflow( 4170 Code, 4171 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4172 ASTContext &ASTCtx) { 4173 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4174 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4175 4176 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4177 ASSERT_THAT(BarDecl, NotNull()); 4178 4179 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4180 ASSERT_THAT(BazDecl, NotNull()); 4181 4182 const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl); 4183 ASSERT_THAT(BarLoc, NotNull()); 4184 4185 const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl); 4186 EXPECT_EQ(BazLoc, BarLoc); 4187 }); 4188 } 4189 4190 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) { 4191 std::string Code = R"( 4192 void target(bool Foo) { 4193 if (Foo) { 4194 (void)0; 4195 // [[if_then]] 4196 } else { 4197 (void)0; 4198 // [[if_else]] 4199 } 4200 } 4201 )"; 4202 runDataflow( 4203 Code, 4204 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4205 ASTContext &ASTCtx) { 4206 ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else")); 4207 const Environment &ThenEnv = 4208 getEnvironmentAtAnnotation(Results, "if_then"); 4209 const Environment &ElseEnv = 4210 getEnvironmentAtAnnotation(Results, "if_else"); 4211 4212 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4213 ASSERT_THAT(FooDecl, NotNull()); 4214 4215 BoolValue &ThenFooVal = *cast<BoolValue>(ThenEnv.getValue(*FooDecl)); 4216 EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal)); 4217 4218 BoolValue &ElseFooVal = *cast<BoolValue>(ElseEnv.getValue(*FooDecl)); 4219 EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal))); 4220 }); 4221 } 4222 4223 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) { 4224 std::string Code = R"( 4225 void target(bool Foo) { 4226 while (Foo) { 4227 (void)0; 4228 // [[loop_body]] 4229 } 4230 (void)0; 4231 // [[after_loop]] 4232 } 4233 )"; 4234 runDataflow( 4235 Code, 4236 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4237 ASTContext &ASTCtx) { 4238 ASSERT_THAT(Results.keys(), 4239 UnorderedElementsAre("loop_body", "after_loop")); 4240 const Environment &LoopBodyEnv = 4241 getEnvironmentAtAnnotation(Results, "loop_body"); 4242 const Environment &AfterLoopEnv = 4243 getEnvironmentAtAnnotation(Results, "after_loop"); 4244 4245 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4246 ASSERT_THAT(FooDecl, NotNull()); 4247 4248 BoolValue &LoopBodyFooVal = 4249 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl)); 4250 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4251 4252 BoolValue &AfterLoopFooVal = 4253 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl)); 4254 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4255 AfterLoopEnv.makeNot(AfterLoopFooVal))); 4256 }); 4257 } 4258 4259 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) { 4260 std::string Code = R"( 4261 void target(bool Foo) { 4262 bool Bar = true; 4263 do { 4264 (void)0; 4265 // [[loop_body]] 4266 Bar = false; 4267 } while (Foo); 4268 (void)0; 4269 // [[after_loop]] 4270 } 4271 )"; 4272 runDataflow( 4273 Code, 4274 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4275 ASTContext &ASTCtx) { 4276 ASSERT_THAT(Results.keys(), 4277 UnorderedElementsAre("loop_body", "after_loop")); 4278 const Environment &LoopBodyEnv = 4279 getEnvironmentAtAnnotation(Results, "loop_body"); 4280 const Environment &AfterLoopEnv = 4281 getEnvironmentAtAnnotation(Results, "after_loop"); 4282 4283 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4284 ASSERT_THAT(FooDecl, NotNull()); 4285 4286 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4287 ASSERT_THAT(BarDecl, NotNull()); 4288 4289 BoolValue &LoopBodyFooVal = 4290 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl)); 4291 BoolValue &LoopBodyBarVal = 4292 *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl)); 4293 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies( 4294 LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal))); 4295 4296 BoolValue &AfterLoopFooVal = 4297 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl)); 4298 BoolValue &AfterLoopBarVal = 4299 *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl)); 4300 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4301 AfterLoopEnv.makeNot(AfterLoopFooVal))); 4302 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4303 AfterLoopEnv.makeNot(AfterLoopBarVal))); 4304 }); 4305 } 4306 4307 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) { 4308 std::string Code = R"( 4309 void target(bool Foo) { 4310 for (; Foo;) { 4311 (void)0; 4312 // [[loop_body]] 4313 } 4314 (void)0; 4315 // [[after_loop]] 4316 } 4317 )"; 4318 runDataflow( 4319 Code, 4320 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4321 ASTContext &ASTCtx) { 4322 ASSERT_THAT(Results.keys(), 4323 UnorderedElementsAre("loop_body", "after_loop")); 4324 const Environment &LoopBodyEnv = 4325 getEnvironmentAtAnnotation(Results, "loop_body"); 4326 const Environment &AfterLoopEnv = 4327 getEnvironmentAtAnnotation(Results, "after_loop"); 4328 4329 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4330 ASSERT_THAT(FooDecl, NotNull()); 4331 4332 BoolValue &LoopBodyFooVal = 4333 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl)); 4334 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4335 4336 BoolValue &AfterLoopFooVal = 4337 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl)); 4338 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4339 AfterLoopEnv.makeNot(AfterLoopFooVal))); 4340 }); 4341 } 4342 4343 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) { 4344 std::string Code = R"( 4345 void target(bool Foo) { 4346 for (;;) { 4347 (void)0; 4348 // [[loop_body]] 4349 } 4350 } 4351 )"; 4352 runDataflow( 4353 Code, 4354 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4355 ASTContext &ASTCtx) { 4356 ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body")); 4357 const Environment &LoopBodyEnv = 4358 getEnvironmentAtAnnotation(Results, "loop_body"); 4359 4360 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4361 ASSERT_THAT(FooDecl, NotNull()); 4362 4363 BoolValue &LoopBodyFooVal = 4364 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl)); 4365 EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4366 }); 4367 } 4368 4369 TEST(TransferTest, ContextSensitiveOptionDisabled) { 4370 std::string Code = R"( 4371 bool GiveBool(); 4372 void SetBool(bool &Var) { Var = true; } 4373 4374 void target() { 4375 bool Foo = GiveBool(); 4376 SetBool(Foo); 4377 // [[p]] 4378 } 4379 )"; 4380 runDataflow( 4381 Code, 4382 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4383 ASTContext &ASTCtx) { 4384 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4385 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4386 4387 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4388 ASSERT_THAT(FooDecl, NotNull()); 4389 4390 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4391 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4392 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4393 }, 4394 {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}}); 4395 } 4396 4397 TEST(TransferTest, ContextSensitiveReturnReference) { 4398 std::string Code = R"( 4399 class S {}; 4400 S& target(bool b, S &s) { 4401 return s; 4402 // [[p]] 4403 } 4404 )"; 4405 runDataflow( 4406 Code, 4407 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4408 ASTContext &ASTCtx) { 4409 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4410 4411 const ValueDecl *SDecl = findValueDecl(ASTCtx, "s"); 4412 ASSERT_THAT(SDecl, NotNull()); 4413 4414 auto *SLoc = Env.getStorageLocation(*SDecl); 4415 ASSERT_THAT(SLoc, NotNull()); 4416 4417 ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc)); 4418 }, 4419 {BuiltinOptions{ContextSensitiveOptions{}}}); 4420 } 4421 4422 // This test is a regression test, based on a real crash. 4423 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) { 4424 std::string Code = R"( 4425 class S {}; 4426 S& target(bool b, S &s) { 4427 return b ? s : s; 4428 // [[p]] 4429 } 4430 )"; 4431 runDataflow( 4432 Code, 4433 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4434 ASTContext &ASTCtx) { 4435 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4436 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4437 4438 const ValueDecl *SDecl = findValueDecl(ASTCtx, "s"); 4439 ASSERT_THAT(SDecl, NotNull()); 4440 4441 auto *SLoc = Env.getStorageLocation(*SDecl); 4442 ASSERT_THAT(SLoc, NotNull()); 4443 EXPECT_THAT(Env.getValue(*SLoc), NotNull()); 4444 4445 auto *Loc = Env.getReturnStorageLocation(); 4446 ASSERT_THAT(Loc, NotNull()); 4447 EXPECT_THAT(Env.getValue(*Loc), NotNull()); 4448 4449 // TODO: We would really like to make this stronger assertion, but that 4450 // doesn't work because we don't propagate values correctly through 4451 // the conditional operator yet. 4452 // ASSERT_THAT(Loc, Eq(SLoc)); 4453 }, 4454 {BuiltinOptions{ContextSensitiveOptions{}}}); 4455 } 4456 4457 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) { 4458 std::string Code = R"( 4459 class S {}; 4460 S &callee(bool b, S &s1_parm, S &s2_parm) { 4461 if (b) 4462 return s1_parm; 4463 else 4464 return s2_parm; 4465 } 4466 void target(bool b) { 4467 S s1; 4468 S s2; 4469 S &return_s1 = s1; 4470 S &return_s2 = s2; 4471 S &return_dont_know = callee(b, s1, s2); 4472 // [[p]] 4473 } 4474 )"; 4475 runDataflow( 4476 Code, 4477 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4478 ASTContext &ASTCtx) { 4479 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4480 4481 const ValueDecl *S1 = findValueDecl(ASTCtx, "s1"); 4482 ASSERT_THAT(S1, NotNull()); 4483 const ValueDecl *S2 = findValueDecl(ASTCtx, "s2"); 4484 ASSERT_THAT(S2, NotNull()); 4485 const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1"); 4486 ASSERT_THAT(ReturnS1, NotNull()); 4487 const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2"); 4488 ASSERT_THAT(ReturnS2, NotNull()); 4489 const ValueDecl *ReturnDontKnow = 4490 findValueDecl(ASTCtx, "return_dont_know"); 4491 ASSERT_THAT(ReturnDontKnow, NotNull()); 4492 4493 StorageLocation *S1Loc = Env.getStorageLocation(*S1); 4494 StorageLocation *S2Loc = Env.getStorageLocation(*S2); 4495 4496 EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc)); 4497 EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc)); 4498 4499 // In the case where we don't have a consistent storage location for 4500 // the return value, the framework creates a new storage location, which 4501 // should be different from the storage locations of `s1` and `s2`. 4502 EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc)); 4503 EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc)); 4504 }, 4505 {BuiltinOptions{ContextSensitiveOptions{}}}); 4506 } 4507 4508 TEST(TransferTest, ContextSensitiveDepthZero) { 4509 std::string Code = R"( 4510 bool GiveBool(); 4511 void SetBool(bool &Var) { Var = true; } 4512 4513 void target() { 4514 bool Foo = GiveBool(); 4515 SetBool(Foo); 4516 // [[p]] 4517 } 4518 )"; 4519 runDataflow( 4520 Code, 4521 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4522 ASTContext &ASTCtx) { 4523 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4524 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4525 4526 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4527 ASSERT_THAT(FooDecl, NotNull()); 4528 4529 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4530 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4531 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4532 }, 4533 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}}); 4534 } 4535 4536 TEST(TransferTest, ContextSensitiveSetTrue) { 4537 std::string Code = R"( 4538 bool GiveBool(); 4539 void SetBool(bool &Var) { Var = true; } 4540 4541 void target() { 4542 bool Foo = GiveBool(); 4543 SetBool(Foo); 4544 // [[p]] 4545 } 4546 )"; 4547 runDataflow( 4548 Code, 4549 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4550 ASTContext &ASTCtx) { 4551 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4552 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4553 4554 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4555 ASSERT_THAT(FooDecl, NotNull()); 4556 4557 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4558 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4559 }, 4560 {BuiltinOptions{ContextSensitiveOptions{}}}); 4561 } 4562 4563 TEST(TransferTest, ContextSensitiveSetFalse) { 4564 std::string Code = R"( 4565 bool GiveBool(); 4566 void SetBool(bool &Var) { Var = false; } 4567 4568 void target() { 4569 bool Foo = GiveBool(); 4570 SetBool(Foo); 4571 // [[p]] 4572 } 4573 )"; 4574 runDataflow( 4575 Code, 4576 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4577 ASTContext &ASTCtx) { 4578 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4579 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4580 4581 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4582 ASSERT_THAT(FooDecl, NotNull()); 4583 4584 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4585 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4586 }, 4587 {BuiltinOptions{ContextSensitiveOptions{}}}); 4588 } 4589 4590 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) { 4591 std::string Code = R"( 4592 bool GiveBool(); 4593 void SetBool(bool &Var, bool Val) { Var = Val; } 4594 4595 void target() { 4596 bool Foo = GiveBool(); 4597 bool Bar = GiveBool(); 4598 SetBool(Foo, true); 4599 SetBool(Bar, false); 4600 // [[p]] 4601 } 4602 )"; 4603 runDataflow( 4604 Code, 4605 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4606 ASTContext &ASTCtx) { 4607 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4608 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4609 4610 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4611 ASSERT_THAT(FooDecl, NotNull()); 4612 4613 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4614 ASSERT_THAT(BarDecl, NotNull()); 4615 4616 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4617 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4618 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4619 4620 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 4621 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4622 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4623 }, 4624 {BuiltinOptions{ContextSensitiveOptions{}}}); 4625 } 4626 4627 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) { 4628 std::string Code = R"( 4629 bool GiveBool(); 4630 void SetBool1(bool &Var) { Var = true; } 4631 void SetBool2(bool &Var) { SetBool1(Var); } 4632 4633 void target() { 4634 bool Foo = GiveBool(); 4635 SetBool2(Foo); 4636 // [[p]] 4637 } 4638 )"; 4639 runDataflow( 4640 Code, 4641 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4642 ASTContext &ASTCtx) { 4643 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4644 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4645 4646 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4647 ASSERT_THAT(FooDecl, NotNull()); 4648 4649 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4650 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4651 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4652 }, 4653 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}}); 4654 } 4655 4656 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) { 4657 std::string Code = R"( 4658 bool GiveBool(); 4659 void SetBool1(bool &Var) { Var = true; } 4660 void SetBool2(bool &Var) { SetBool1(Var); } 4661 4662 void target() { 4663 bool Foo = GiveBool(); 4664 SetBool2(Foo); 4665 // [[p]] 4666 } 4667 )"; 4668 runDataflow( 4669 Code, 4670 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4671 ASTContext &ASTCtx) { 4672 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4673 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4674 4675 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4676 ASSERT_THAT(FooDecl, NotNull()); 4677 4678 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4679 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4680 }, 4681 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}}); 4682 } 4683 4684 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) { 4685 std::string Code = R"( 4686 bool GiveBool(); 4687 void SetBool1(bool &Var) { Var = true; } 4688 void SetBool2(bool &Var) { SetBool1(Var); } 4689 void SetBool3(bool &Var) { SetBool2(Var); } 4690 4691 void target() { 4692 bool Foo = GiveBool(); 4693 SetBool3(Foo); 4694 // [[p]] 4695 } 4696 )"; 4697 runDataflow( 4698 Code, 4699 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4700 ASTContext &ASTCtx) { 4701 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4702 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4703 4704 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4705 ASSERT_THAT(FooDecl, NotNull()); 4706 4707 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4708 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4709 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4710 }, 4711 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}}); 4712 } 4713 4714 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) { 4715 std::string Code = R"( 4716 bool GiveBool(); 4717 void SetBool1(bool &Var) { Var = true; } 4718 void SetBool2(bool &Var) { SetBool1(Var); } 4719 void SetBool3(bool &Var) { SetBool2(Var); } 4720 4721 void target() { 4722 bool Foo = GiveBool(); 4723 SetBool3(Foo); 4724 // [[p]] 4725 } 4726 )"; 4727 runDataflow( 4728 Code, 4729 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4730 ASTContext &ASTCtx) { 4731 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4732 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4733 4734 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4735 ASSERT_THAT(FooDecl, NotNull()); 4736 4737 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4738 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4739 }, 4740 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}}); 4741 } 4742 4743 TEST(TransferTest, ContextSensitiveMutualRecursion) { 4744 std::string Code = R"( 4745 bool Pong(bool X, bool Y); 4746 4747 bool Ping(bool X, bool Y) { 4748 if (X) { 4749 return Y; 4750 } else { 4751 return Pong(!X, Y); 4752 } 4753 } 4754 4755 bool Pong(bool X, bool Y) { 4756 if (Y) { 4757 return X; 4758 } else { 4759 return Ping(X, !Y); 4760 } 4761 } 4762 4763 void target() { 4764 bool Foo = Ping(false, false); 4765 // [[p]] 4766 } 4767 )"; 4768 runDataflow( 4769 Code, 4770 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4771 ASTContext &ASTCtx) { 4772 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4773 // The analysis doesn't crash... 4774 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4775 4776 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4777 ASSERT_THAT(FooDecl, NotNull()); 4778 4779 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4780 // ... but it also can't prove anything here. 4781 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4782 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4783 }, 4784 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}}); 4785 } 4786 4787 TEST(TransferTest, ContextSensitiveSetMultipleLines) { 4788 std::string Code = R"( 4789 void SetBools(bool &Var1, bool &Var2) { 4790 Var1 = true; 4791 Var2 = false; 4792 } 4793 4794 void target() { 4795 bool Foo = false; 4796 bool Bar = true; 4797 SetBools(Foo, Bar); 4798 // [[p]] 4799 } 4800 )"; 4801 runDataflow( 4802 Code, 4803 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4804 ASTContext &ASTCtx) { 4805 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4806 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4807 4808 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4809 ASSERT_THAT(FooDecl, NotNull()); 4810 4811 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4812 ASSERT_THAT(BarDecl, NotNull()); 4813 4814 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4815 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4816 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4817 4818 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 4819 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4820 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4821 }, 4822 {BuiltinOptions{ContextSensitiveOptions{}}}); 4823 } 4824 4825 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) { 4826 std::string Code = R"( 4827 void IfCond(bool Cond, bool &Then, bool &Else) { 4828 if (Cond) { 4829 Then = true; 4830 } else { 4831 Else = true; 4832 } 4833 } 4834 4835 void target() { 4836 bool Foo = false; 4837 bool Bar = false; 4838 bool Baz = false; 4839 IfCond(Foo, Bar, Baz); 4840 // [[p]] 4841 } 4842 )"; 4843 runDataflow( 4844 Code, 4845 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4846 ASTContext &ASTCtx) { 4847 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4848 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4849 4850 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4851 ASSERT_THAT(BarDecl, NotNull()); 4852 4853 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4854 ASSERT_THAT(BazDecl, NotNull()); 4855 4856 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 4857 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4858 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4859 4860 auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl)); 4861 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 4862 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal))); 4863 }, 4864 {BuiltinOptions{ContextSensitiveOptions{}}}); 4865 } 4866 4867 TEST(TransferTest, ContextSensitiveReturnVoid) { 4868 std::string Code = R"( 4869 void Noop() { return; } 4870 4871 void target() { 4872 Noop(); 4873 // [[p]] 4874 } 4875 )"; 4876 runDataflow( 4877 Code, 4878 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4879 ASTContext &ASTCtx) { 4880 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4881 // This just tests that the analysis doesn't crash. 4882 }, 4883 {BuiltinOptions{ContextSensitiveOptions{}}}); 4884 } 4885 4886 TEST(TransferTest, ContextSensitiveReturnTrue) { 4887 std::string Code = R"( 4888 bool GiveBool() { return true; } 4889 4890 void target() { 4891 bool Foo = GiveBool(); 4892 // [[p]] 4893 } 4894 )"; 4895 runDataflow( 4896 Code, 4897 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4898 ASTContext &ASTCtx) { 4899 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4900 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4901 4902 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4903 ASSERT_THAT(FooDecl, NotNull()); 4904 4905 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4906 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4907 }, 4908 {BuiltinOptions{ContextSensitiveOptions{}}}); 4909 } 4910 4911 TEST(TransferTest, ContextSensitiveReturnFalse) { 4912 std::string Code = R"( 4913 bool GiveBool() { return false; } 4914 4915 void target() { 4916 bool Foo = GiveBool(); 4917 // [[p]] 4918 } 4919 )"; 4920 runDataflow( 4921 Code, 4922 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4923 ASTContext &ASTCtx) { 4924 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4925 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4926 4927 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4928 ASSERT_THAT(FooDecl, NotNull()); 4929 4930 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4931 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4932 }, 4933 {BuiltinOptions{ContextSensitiveOptions{}}}); 4934 } 4935 4936 TEST(TransferTest, ContextSensitiveReturnArg) { 4937 std::string Code = R"( 4938 bool GiveBool(); 4939 bool GiveBack(bool Arg) { return Arg; } 4940 4941 void target() { 4942 bool Foo = GiveBool(); 4943 bool Bar = GiveBack(Foo); 4944 bool Baz = Foo == Bar; 4945 // [[p]] 4946 } 4947 )"; 4948 runDataflow( 4949 Code, 4950 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4951 ASTContext &ASTCtx) { 4952 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4953 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4954 4955 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4956 ASSERT_THAT(BazDecl, NotNull()); 4957 4958 auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl)); 4959 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 4960 }, 4961 {BuiltinOptions{ContextSensitiveOptions{}}}); 4962 } 4963 4964 TEST(TransferTest, ContextSensitiveReturnInt) { 4965 std::string Code = R"( 4966 int identity(int x) { return x; } 4967 4968 void target() { 4969 int y = identity(42); 4970 // [[p]] 4971 } 4972 )"; 4973 runDataflow( 4974 Code, 4975 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4976 ASTContext &ASTCtx) { 4977 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4978 // This just tests that the analysis doesn't crash. 4979 }, 4980 {BuiltinOptions{ContextSensitiveOptions{}}}); 4981 } 4982 4983 TEST(TransferTest, ContextSensitiveMethodLiteral) { 4984 std::string Code = R"( 4985 class MyClass { 4986 public: 4987 bool giveBool() { return true; } 4988 }; 4989 4990 void target() { 4991 MyClass MyObj; 4992 bool Foo = MyObj.giveBool(); 4993 // [[p]] 4994 } 4995 )"; 4996 runDataflow( 4997 Code, 4998 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4999 ASTContext &ASTCtx) { 5000 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5001 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5002 5003 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5004 ASSERT_THAT(FooDecl, NotNull()); 5005 5006 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5007 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5008 }, 5009 {BuiltinOptions{ContextSensitiveOptions{}}}); 5010 } 5011 5012 TEST(TransferTest, ContextSensitiveMethodGetter) { 5013 std::string Code = R"( 5014 class MyClass { 5015 public: 5016 bool getField() { return Field; } 5017 5018 bool Field; 5019 }; 5020 5021 void target() { 5022 MyClass MyObj; 5023 MyObj.Field = true; 5024 bool Foo = MyObj.getField(); 5025 // [[p]] 5026 } 5027 )"; 5028 runDataflow( 5029 Code, 5030 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5031 ASTContext &ASTCtx) { 5032 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5033 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5034 5035 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5036 ASSERT_THAT(FooDecl, NotNull()); 5037 5038 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5039 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5040 }, 5041 {BuiltinOptions{ContextSensitiveOptions{}}}); 5042 } 5043 5044 TEST(TransferTest, ContextSensitiveMethodSetter) { 5045 std::string Code = R"( 5046 class MyClass { 5047 public: 5048 void setField(bool Val) { Field = Val; } 5049 5050 bool Field; 5051 }; 5052 5053 void target() { 5054 MyClass MyObj; 5055 MyObj.setField(true); 5056 bool Foo = MyObj.Field; 5057 // [[p]] 5058 } 5059 )"; 5060 runDataflow( 5061 Code, 5062 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5063 ASTContext &ASTCtx) { 5064 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5065 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5066 5067 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5068 ASSERT_THAT(FooDecl, NotNull()); 5069 5070 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5071 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5072 }, 5073 {BuiltinOptions{ContextSensitiveOptions{}}}); 5074 } 5075 5076 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) { 5077 std::string Code = R"( 5078 class MyClass { 5079 public: 5080 bool getField() { return Field; } 5081 void setField(bool Val) { Field = Val; } 5082 5083 private: 5084 bool Field; 5085 }; 5086 5087 void target() { 5088 MyClass MyObj; 5089 MyObj.setField(true); 5090 bool Foo = MyObj.getField(); 5091 // [[p]] 5092 } 5093 )"; 5094 runDataflow( 5095 Code, 5096 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5097 ASTContext &ASTCtx) { 5098 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5099 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5100 5101 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5102 ASSERT_THAT(FooDecl, NotNull()); 5103 5104 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5105 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5106 }, 5107 {BuiltinOptions{ContextSensitiveOptions{}}}); 5108 } 5109 5110 5111 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) { 5112 std::string Code = R"( 5113 class MyClass { 5114 public: 5115 void Inner() { MyField = true; } 5116 void Outer() { Inner(); } 5117 5118 bool MyField; 5119 }; 5120 5121 void target() { 5122 MyClass MyObj; 5123 MyObj.Outer(); 5124 bool Foo = MyObj.MyField; 5125 // [[p]] 5126 } 5127 )"; 5128 runDataflow( 5129 Code, 5130 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5131 ASTContext &ASTCtx) { 5132 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5133 ; 5134 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5135 5136 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5137 ASSERT_THAT(FooDecl, NotNull()); 5138 5139 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5140 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5141 }, 5142 {BuiltinOptions{ContextSensitiveOptions{}}}); 5143 } 5144 5145 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) { 5146 std::string Code = R"( 5147 class MyClass { 5148 public: 5149 bool Inner() { return MyField; } 5150 bool Outer() { return Inner(); } 5151 5152 bool MyField; 5153 }; 5154 5155 void target() { 5156 MyClass MyObj; 5157 MyObj.MyField = true; 5158 bool Foo = MyObj.Outer(); 5159 // [[p]] 5160 } 5161 )"; 5162 runDataflow( 5163 Code, 5164 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5165 ASTContext &ASTCtx) { 5166 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5167 ; 5168 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5169 5170 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5171 ASSERT_THAT(FooDecl, NotNull()); 5172 5173 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5174 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5175 }, 5176 {BuiltinOptions{ContextSensitiveOptions{}}}); 5177 } 5178 5179 TEST(TransferTest, ContextSensitiveConstructorBody) { 5180 std::string Code = R"( 5181 class MyClass { 5182 public: 5183 MyClass() { MyField = true; } 5184 5185 bool MyField; 5186 }; 5187 5188 void target() { 5189 MyClass MyObj; 5190 bool Foo = MyObj.MyField; 5191 // [[p]] 5192 } 5193 )"; 5194 runDataflow( 5195 Code, 5196 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5197 ASTContext &ASTCtx) { 5198 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5199 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5200 5201 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5202 ASSERT_THAT(FooDecl, NotNull()); 5203 5204 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5205 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5206 }, 5207 {BuiltinOptions{ContextSensitiveOptions{}}}); 5208 } 5209 5210 TEST(TransferTest, ContextSensitiveConstructorInitializer) { 5211 std::string Code = R"( 5212 class MyClass { 5213 public: 5214 MyClass() : MyField(true) {} 5215 5216 bool MyField; 5217 }; 5218 5219 void target() { 5220 MyClass MyObj; 5221 bool Foo = MyObj.MyField; 5222 // [[p]] 5223 } 5224 )"; 5225 runDataflow( 5226 Code, 5227 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5228 ASTContext &ASTCtx) { 5229 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5230 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5231 5232 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5233 ASSERT_THAT(FooDecl, NotNull()); 5234 5235 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5236 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5237 }, 5238 {BuiltinOptions{ContextSensitiveOptions{}}}); 5239 } 5240 5241 TEST(TransferTest, ContextSensitiveConstructorDefault) { 5242 std::string Code = R"( 5243 class MyClass { 5244 public: 5245 MyClass() = default; 5246 5247 bool MyField = true; 5248 }; 5249 5250 void target() { 5251 MyClass MyObj; 5252 bool Foo = MyObj.MyField; 5253 // [[p]] 5254 } 5255 )"; 5256 runDataflow( 5257 Code, 5258 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5259 ASTContext &ASTCtx) { 5260 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5261 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5262 5263 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5264 ASSERT_THAT(FooDecl, NotNull()); 5265 5266 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5267 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5268 }, 5269 {BuiltinOptions{ContextSensitiveOptions{}}}); 5270 } 5271 5272 TEST(TransferTest, UnnamedBitfieldInitializer) { 5273 std::string Code = R"( 5274 struct B {}; 5275 struct A { 5276 unsigned a; 5277 unsigned : 4; 5278 unsigned c; 5279 B b; 5280 }; 5281 void target() { 5282 A a = {}; 5283 A test = a; 5284 (void)test.c; 5285 } 5286 )"; 5287 runDataflow( 5288 Code, 5289 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5290 ASTContext &ASTCtx) { 5291 // This doesn't need a body because this test was crashing the framework 5292 // before handling correctly Unnamed bitfields in `InitListExpr`. 5293 }); 5294 } 5295 5296 // Repro for a crash that used to occur with chained short-circuiting logical 5297 // operators. 5298 TEST(TransferTest, ChainedLogicalOps) { 5299 std::string Code = R"( 5300 bool target() { 5301 bool b = true || false || false || false; 5302 // [[p]] 5303 return b; 5304 } 5305 )"; 5306 runDataflow( 5307 Code, 5308 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5309 ASTContext &ASTCtx) { 5310 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5311 auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b"); 5312 EXPECT_TRUE(Env.flowConditionImplies(B)); 5313 }); 5314 } 5315 5316 // Repro for a crash that used to occur when we call a `noreturn` function 5317 // within one of the operands of a `&&` or `||` operator. 5318 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) { 5319 std::string Code = R"( 5320 __attribute__((noreturn)) int doesnt_return(); 5321 bool some_condition(); 5322 void target(bool b1, bool b2) { 5323 // Neither of these should crash. In addition, if we don't terminate the 5324 // program, we know that the operators need to trigger the short-circuit 5325 // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr` 5326 // will be true. 5327 bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0; 5328 bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0; 5329 5330 // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the 5331 // entire expression unreachable. So we know that in both of the following 5332 // cases, if `target()` terminates, the `else` branch was taken. 5333 bool NoreturnOnLhsMakesAndUnreachable = false; 5334 if (some_condition()) 5335 doesnt_return() > 0 && some_condition(); 5336 else 5337 NoreturnOnLhsMakesAndUnreachable = true; 5338 5339 bool NoreturnOnLhsMakesOrUnreachable = false; 5340 if (some_condition()) 5341 doesnt_return() > 0 || some_condition(); 5342 else 5343 NoreturnOnLhsMakesOrUnreachable = true; 5344 5345 // [[p]] 5346 } 5347 )"; 5348 runDataflow( 5349 Code, 5350 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5351 ASTContext &ASTCtx) { 5352 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5353 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5354 5355 // Check that [[p]] is reachable with a non-false flow condition. 5356 EXPECT_FALSE(Env.flowConditionImplies(Env.getBoolLiteralValue(false))); 5357 5358 auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1"); 5359 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(B1))); 5360 5361 auto &NoreturnOnRhsOfAnd = 5362 getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd"); 5363 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(NoreturnOnRhsOfAnd))); 5364 5365 auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2"); 5366 EXPECT_TRUE(Env.flowConditionImplies(B2)); 5367 5368 auto &NoreturnOnRhsOfOr = 5369 getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr"); 5370 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnRhsOfOr)); 5371 5372 auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>( 5373 ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable"); 5374 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesAndUnreachable)); 5375 5376 auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>( 5377 ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable"); 5378 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesOrUnreachable)); 5379 }); 5380 } 5381 5382 TEST(TransferTest, NewExpressions) { 5383 std::string Code = R"( 5384 void target() { 5385 int *p = new int(42); 5386 // [[after_new]] 5387 } 5388 )"; 5389 runDataflow( 5390 Code, 5391 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5392 ASTContext &ASTCtx) { 5393 const Environment &Env = 5394 getEnvironmentAtAnnotation(Results, "after_new"); 5395 5396 auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p"); 5397 5398 EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull()); 5399 }); 5400 } 5401 5402 TEST(TransferTest, NewExpressions_Structs) { 5403 std::string Code = R"( 5404 struct Inner { 5405 int InnerField; 5406 }; 5407 5408 struct Outer { 5409 Inner OuterField; 5410 }; 5411 5412 void target() { 5413 Outer *p = new Outer; 5414 // Access the fields to make sure the analysis actually generates children 5415 // for them in the `AggregateStorageLoc` and `StructValue`. 5416 p->OuterField.InnerField; 5417 // [[after_new]] 5418 } 5419 )"; 5420 runDataflow( 5421 Code, 5422 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5423 ASTContext &ASTCtx) { 5424 const Environment &Env = 5425 getEnvironmentAtAnnotation(Results, "after_new"); 5426 5427 const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField"); 5428 const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField"); 5429 5430 auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p"); 5431 5432 auto &OuterLoc = cast<AggregateStorageLocation>(P.getPointeeLoc()); 5433 auto &OuterFieldLoc = 5434 cast<AggregateStorageLocation>(OuterLoc.getChild(*OuterField)); 5435 auto &InnerFieldLoc = OuterFieldLoc.getChild(*InnerField); 5436 5437 // Values for the struct and all fields exist after the new. 5438 EXPECT_THAT(Env.getValue(OuterLoc), NotNull()); 5439 EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull()); 5440 EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull()); 5441 }); 5442 } 5443 5444 TEST(TransferTest, FunctionToPointerDecayHasValue) { 5445 std::string Code = R"( 5446 struct A { static void static_member_func(); }; 5447 void target() { 5448 // To check that we're treating function-to-pointer decay correctly, 5449 // create two pointers, then verify they refer to the same storage 5450 // location. 5451 // We need to do the test this way because even if an initializer (in this 5452 // case, the function-to-pointer decay) does not create a value, we still 5453 // create a value for the variable. 5454 void (*non_member_p1)() = target; 5455 void (*non_member_p2)() = target; 5456 5457 // Do the same thing but for a static member function. 5458 void (*member_p1)() = A::static_member_func; 5459 void (*member_p2)() = A::static_member_func; 5460 // [[p]] 5461 } 5462 )"; 5463 runDataflow( 5464 Code, 5465 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5466 ASTContext &ASTCtx) { 5467 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5468 5469 auto &NonMemberP1 = 5470 getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1"); 5471 auto &NonMemberP2 = 5472 getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2"); 5473 EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc()); 5474 5475 auto &MemberP1 = 5476 getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1"); 5477 auto &MemberP2 = 5478 getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2"); 5479 EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc()); 5480 }); 5481 } 5482 5483 // Check that a builtin function is not associated with a value. (It's only 5484 // possible to call builtin functions directly, not take their address.) 5485 TEST(TransferTest, BuiltinFunctionModeled) { 5486 std::string Code = R"( 5487 void target() { 5488 __builtin_expect(0, 0); 5489 // [[p]] 5490 } 5491 )"; 5492 runDataflow( 5493 Code, 5494 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5495 ASTContext &ASTCtx) { 5496 using ast_matchers::selectFirst; 5497 using ast_matchers::match; 5498 using ast_matchers::traverse; 5499 using ast_matchers::implicitCastExpr; 5500 using ast_matchers::hasCastKind; 5501 5502 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5503 5504 auto *ImplicitCast = selectFirst<ImplicitCastExpr>( 5505 "implicit_cast", 5506 match(traverse(TK_AsIs, 5507 implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr)) 5508 .bind("implicit_cast")), 5509 ASTCtx)); 5510 5511 ASSERT_THAT(ImplicitCast, NotNull()); 5512 EXPECT_THAT(Env.getValueStrict(*ImplicitCast), IsNull()); 5513 }); 5514 } 5515 5516 // Check that fields of anonymous records are modeled. 5517 TEST(TransferTest, AnonymousStruct) { 5518 std::string Code = R"( 5519 struct S { 5520 struct { 5521 bool b; 5522 }; 5523 }; 5524 void target() { 5525 S s; 5526 s.b = true; 5527 // [[p]] 5528 } 5529 )"; 5530 runDataflow( 5531 Code, 5532 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5533 ASTContext &ASTCtx) { 5534 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5535 const ValueDecl *SDecl = findValueDecl(ASTCtx, "s"); 5536 const ValueDecl *BDecl = findValueDecl(ASTCtx, "b"); 5537 const IndirectFieldDecl *IndirectField = 5538 findIndirectFieldDecl(ASTCtx, "b"); 5539 5540 auto *S = 5541 cast<AggregateStorageLocation>(Env.getStorageLocation(*SDecl)); 5542 auto &AnonStruct = cast<AggregateStorageLocation>( 5543 S->getChild(*cast<ValueDecl>(IndirectField->chain().front()))); 5544 5545 auto *B = cast<BoolValue>(Env.getValue(AnonStruct.getChild(*BDecl))); 5546 ASSERT_TRUE(Env.flowConditionImplies(*B)); 5547 }); 5548 } 5549 5550 TEST(TransferTest, AnonymousStructWithInitializer) { 5551 std::string Code = R"( 5552 struct target { 5553 target() { 5554 (void)0; 5555 // [[p]] 5556 } 5557 struct { 5558 bool b = true; 5559 }; 5560 }; 5561 )"; 5562 runDataflow( 5563 Code, 5564 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5565 ASTContext &ASTCtx) { 5566 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5567 const ValueDecl *BDecl = findValueDecl(ASTCtx, "b"); 5568 const IndirectFieldDecl *IndirectField = 5569 findIndirectFieldDecl(ASTCtx, "b"); 5570 5571 auto *ThisLoc = 5572 cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation()); 5573 auto &AnonStruct = cast<AggregateStorageLocation>(ThisLoc->getChild( 5574 *cast<ValueDecl>(IndirectField->chain().front()))); 5575 5576 auto *B = cast<BoolValue>(Env.getValue(AnonStruct.getChild(*BDecl))); 5577 ASSERT_TRUE(Env.flowConditionImplies(*B)); 5578 }); 5579 } 5580 5581 TEST(TransferTest, AnonymousStructWithReferenceField) { 5582 std::string Code = R"( 5583 int global_i = 0; 5584 struct target { 5585 target() { 5586 (void)0; 5587 // [[p]] 5588 } 5589 struct { 5590 int &i = global_i; 5591 }; 5592 }; 5593 )"; 5594 runDataflow( 5595 Code, 5596 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5597 ASTContext &ASTCtx) { 5598 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5599 const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i"); 5600 const ValueDecl *IDecl = findValueDecl(ASTCtx, "i"); 5601 const IndirectFieldDecl *IndirectField = 5602 findIndirectFieldDecl(ASTCtx, "i"); 5603 5604 auto *ThisLoc = 5605 cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation()); 5606 auto &AnonStruct = cast<AggregateStorageLocation>(ThisLoc->getChild( 5607 *cast<ValueDecl>(IndirectField->chain().front()))); 5608 5609 auto *RefVal = 5610 cast<ReferenceValue>(Env.getValue(AnonStruct.getChild(*IDecl))); 5611 5612 ASSERT_EQ(&RefVal->getReferentLoc(), 5613 Env.getStorageLocation(*GlobalIDecl)); 5614 }); 5615 } 5616 5617 } // namespace 5618