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