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