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