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