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