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