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, StructMemberEnum) { 1070 std::string Code = R"( 1071 struct A { 1072 int Bar; 1073 enum E { ONE, TWO }; 1074 }; 1075 1076 void target(A Foo) { 1077 A::E Baz = Foo.ONE; 1078 // [[p]] 1079 } 1080 )"; 1081 // Minimal expectations -- we're just testing that it doesn't crash, since 1082 // enums aren't interpreted. 1083 runDataflow( 1084 Code, 1085 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1086 ASTContext &ASTCtx) { 1087 EXPECT_THAT(Results.keys(), UnorderedElementsAre("p")); 1088 }); 1089 } 1090 1091 TEST(TransferTest, DerivedBaseMemberClass) { 1092 std::string Code = R"( 1093 class A { 1094 int ADefault; 1095 protected: 1096 int AProtected; 1097 private: 1098 int APrivate; 1099 public: 1100 int APublic; 1101 1102 private: 1103 friend void target(); 1104 }; 1105 1106 class B : public A { 1107 int BDefault; 1108 protected: 1109 int BProtected; 1110 private: 1111 int BPrivate; 1112 1113 private: 1114 friend void target(); 1115 }; 1116 1117 void target() { 1118 B Foo; 1119 (void)Foo.ADefault; 1120 (void)Foo.AProtected; 1121 (void)Foo.APrivate; 1122 (void)Foo.APublic; 1123 (void)Foo.BDefault; 1124 (void)Foo.BProtected; 1125 (void)Foo.BPrivate; 1126 // [[p]] 1127 } 1128 )"; 1129 runDataflow( 1130 Code, 1131 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1132 ASTContext &ASTCtx) { 1133 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1134 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1135 1136 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1137 ASSERT_THAT(FooDecl, NotNull()); 1138 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1139 1140 // Derived-class fields. 1141 const FieldDecl *BDefaultDecl = nullptr; 1142 const FieldDecl *BProtectedDecl = nullptr; 1143 const FieldDecl *BPrivateDecl = nullptr; 1144 for (const FieldDecl *Field : 1145 FooDecl->getType()->getAsRecordDecl()->fields()) { 1146 if (Field->getNameAsString() == "BDefault") { 1147 BDefaultDecl = Field; 1148 } else if (Field->getNameAsString() == "BProtected") { 1149 BProtectedDecl = Field; 1150 } else if (Field->getNameAsString() == "BPrivate") { 1151 BPrivateDecl = Field; 1152 } else { 1153 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1154 } 1155 } 1156 ASSERT_THAT(BDefaultDecl, NotNull()); 1157 ASSERT_THAT(BProtectedDecl, NotNull()); 1158 ASSERT_THAT(BPrivateDecl, NotNull()); 1159 1160 // Base-class fields. 1161 const FieldDecl *ADefaultDecl = nullptr; 1162 const FieldDecl *APrivateDecl = nullptr; 1163 const FieldDecl *AProtectedDecl = nullptr; 1164 const FieldDecl *APublicDecl = nullptr; 1165 for (const clang::CXXBaseSpecifier &Base : 1166 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1167 QualType BaseType = Base.getType(); 1168 ASSERT_TRUE(BaseType->isRecordType()); 1169 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1170 if (Field->getNameAsString() == "ADefault") { 1171 ADefaultDecl = Field; 1172 } else if (Field->getNameAsString() == "AProtected") { 1173 AProtectedDecl = Field; 1174 } else if (Field->getNameAsString() == "APrivate") { 1175 APrivateDecl = Field; 1176 } else if (Field->getNameAsString() == "APublic") { 1177 APublicDecl = Field; 1178 } else { 1179 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1180 } 1181 } 1182 } 1183 ASSERT_THAT(ADefaultDecl, NotNull()); 1184 ASSERT_THAT(AProtectedDecl, NotNull()); 1185 ASSERT_THAT(APrivateDecl, NotNull()); 1186 ASSERT_THAT(APublicDecl, NotNull()); 1187 1188 const auto &FooLoc = *cast<AggregateStorageLocation>( 1189 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1190 const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc)); 1191 1192 // Note: we can't test presence of children in `FooLoc`, because 1193 // `getChild` requires its argument be present (or fails an assert). So, 1194 // we limit to testing presence in `FooVal` and coherence between the 1195 // two. 1196 1197 // Base-class fields. 1198 EXPECT_THAT(FooVal.getChild(*ADefaultDecl), NotNull()); 1199 EXPECT_THAT(FooVal.getChild(*APrivateDecl), NotNull()); 1200 1201 EXPECT_THAT(FooVal.getChild(*AProtectedDecl), NotNull()); 1202 EXPECT_EQ(Env.getValue(FooLoc.getChild(*APublicDecl)), 1203 FooVal.getChild(*APublicDecl)); 1204 EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull()); 1205 EXPECT_EQ(Env.getValue(FooLoc.getChild(*AProtectedDecl)), 1206 FooVal.getChild(*AProtectedDecl)); 1207 1208 // Derived-class fields. 1209 EXPECT_THAT(FooVal.getChild(*BDefaultDecl), NotNull()); 1210 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BDefaultDecl)), 1211 FooVal.getChild(*BDefaultDecl)); 1212 EXPECT_THAT(FooVal.getChild(*BProtectedDecl), NotNull()); 1213 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BProtectedDecl)), 1214 FooVal.getChild(*BProtectedDecl)); 1215 EXPECT_THAT(FooVal.getChild(*BPrivateDecl), NotNull()); 1216 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BPrivateDecl)), 1217 FooVal.getChild(*BPrivateDecl)); 1218 }); 1219 } 1220 1221 static void derivedBaseMemberExpectations( 1222 const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1223 ASTContext &ASTCtx) { 1224 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1225 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1226 1227 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1228 ASSERT_THAT(FooDecl, NotNull()); 1229 1230 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1231 const FieldDecl *BarDecl = nullptr; 1232 for (const clang::CXXBaseSpecifier &Base : 1233 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1234 QualType BaseType = Base.getType(); 1235 ASSERT_TRUE(BaseType->isStructureType()); 1236 1237 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1238 if (Field->getNameAsString() == "Bar") { 1239 BarDecl = Field; 1240 } else { 1241 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1242 } 1243 } 1244 } 1245 ASSERT_THAT(BarDecl, NotNull()); 1246 1247 const auto &FooLoc = *cast<AggregateStorageLocation>( 1248 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1249 const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc)); 1250 EXPECT_THAT(FooVal.getChild(*BarDecl), NotNull()); 1251 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BarDecl)), FooVal.getChild(*BarDecl)); 1252 } 1253 1254 TEST(TransferTest, DerivedBaseMemberStructDefault) { 1255 std::string Code = R"( 1256 struct A { 1257 int Bar; 1258 }; 1259 struct B : public A { 1260 }; 1261 1262 void target() { 1263 B Foo; 1264 (void)Foo.Bar; 1265 // [[p]] 1266 } 1267 )"; 1268 runDataflow(Code, derivedBaseMemberExpectations); 1269 } 1270 1271 TEST(TransferTest, DerivedBaseMemberPrivateFriend) { 1272 // Include an access to `Foo.Bar` to verify the analysis doesn't crash on that 1273 // access. 1274 std::string Code = R"( 1275 struct A { 1276 private: 1277 friend void target(); 1278 int Bar; 1279 }; 1280 struct B : public A { 1281 }; 1282 1283 void target() { 1284 B Foo; 1285 (void)Foo.Bar; 1286 // [[p]] 1287 } 1288 )"; 1289 runDataflow(Code, derivedBaseMemberExpectations); 1290 } 1291 1292 TEST(TransferTest, ClassMember) { 1293 std::string Code = R"( 1294 class A { 1295 public: 1296 int Bar; 1297 }; 1298 1299 void target(A Foo) { 1300 int Baz = Foo.Bar; 1301 // [[p]] 1302 } 1303 )"; 1304 runDataflow( 1305 Code, 1306 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1307 ASTContext &ASTCtx) { 1308 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1309 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1310 1311 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1312 ASSERT_THAT(FooDecl, NotNull()); 1313 1314 ASSERT_TRUE(FooDecl->getType()->isClassType()); 1315 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1316 1317 FieldDecl *BarDecl = nullptr; 1318 for (FieldDecl *Field : FooFields) { 1319 if (Field->getNameAsString() == "Bar") { 1320 BarDecl = Field; 1321 } else { 1322 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1323 } 1324 } 1325 ASSERT_THAT(BarDecl, NotNull()); 1326 1327 const auto *FooLoc = cast<AggregateStorageLocation>( 1328 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1329 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1330 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1331 1332 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1333 ASSERT_THAT(BazDecl, NotNull()); 1334 1335 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal); 1336 }); 1337 } 1338 1339 TEST(TransferTest, BaseClassInitializer) { 1340 using ast_matchers::cxxConstructorDecl; 1341 using ast_matchers::hasName; 1342 using ast_matchers::ofClass; 1343 1344 std::string Code = R"( 1345 class A { 1346 public: 1347 A(int I) : Bar(I) {} 1348 int Bar; 1349 }; 1350 1351 class B : public A { 1352 public: 1353 B(int I) : A(I) { 1354 (void)0; 1355 // [[p]] 1356 } 1357 }; 1358 )"; 1359 ASSERT_THAT_ERROR( 1360 checkDataflow<NoopAnalysis>( 1361 AnalysisInputs<NoopAnalysis>( 1362 Code, cxxConstructorDecl(ofClass(hasName("B"))), 1363 [](ASTContext &C, Environment &) { 1364 return NoopAnalysis(C, /*ApplyBuiltinTransfer=*/true); 1365 }) 1366 .withASTBuildArgs( 1367 {"-fsyntax-only", "-fno-delayed-template-parsing", 1368 "-std=" + std::string(LangStandard::getLangStandardForKind( 1369 LangStandard::lang_cxx17) 1370 .getName())}), 1371 /*VerifyResults=*/ 1372 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1373 const AnalysisOutputs &) { 1374 // Regression test to verify that base-class initializers do not 1375 // trigger an assertion. If we add support for such initializers in 1376 // the future, we can expand this test to check more specific 1377 // properties. 1378 EXPECT_THAT(Results.keys(), UnorderedElementsAre("p")); 1379 }), 1380 llvm::Succeeded()); 1381 } 1382 1383 TEST(TransferTest, ReferenceMember) { 1384 std::string Code = R"( 1385 struct A { 1386 int &Bar; 1387 }; 1388 1389 void target(A Foo) { 1390 int Baz = Foo.Bar; 1391 // [[p]] 1392 } 1393 )"; 1394 runDataflow( 1395 Code, 1396 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1397 ASTContext &ASTCtx) { 1398 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1399 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1400 1401 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1402 ASSERT_THAT(FooDecl, NotNull()); 1403 1404 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1405 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1406 1407 FieldDecl *BarDecl = nullptr; 1408 for (FieldDecl *Field : FooFields) { 1409 if (Field->getNameAsString() == "Bar") { 1410 BarDecl = Field; 1411 } else { 1412 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1413 } 1414 } 1415 ASSERT_THAT(BarDecl, NotNull()); 1416 1417 const auto *FooLoc = cast<AggregateStorageLocation>( 1418 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1419 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1420 const auto *BarVal = cast<ReferenceValue>(FooVal->getChild(*BarDecl)); 1421 const auto *BarReferentVal = 1422 cast<IntegerValue>(Env.getValue(BarVal->getReferentLoc())); 1423 1424 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1425 ASSERT_THAT(BazDecl, NotNull()); 1426 1427 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarReferentVal); 1428 }); 1429 } 1430 1431 TEST(TransferTest, StructThisMember) { 1432 std::string Code = R"( 1433 struct A { 1434 int Bar; 1435 1436 struct B { 1437 int Baz; 1438 }; 1439 1440 B Qux; 1441 1442 void target() { 1443 int Foo = Bar; 1444 int Quux = Qux.Baz; 1445 // [[p]] 1446 } 1447 }; 1448 )"; 1449 runDataflow( 1450 Code, 1451 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1452 ASTContext &ASTCtx) { 1453 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1454 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1455 1456 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1457 Env.getThisPointeeStorageLocation()); 1458 ASSERT_THAT(ThisLoc, NotNull()); 1459 1460 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1461 ASSERT_THAT(BarDecl, NotNull()); 1462 1463 const auto *BarLoc = 1464 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1465 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1466 1467 const Value *BarVal = Env.getValue(*BarLoc); 1468 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1469 1470 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1471 ASSERT_THAT(FooDecl, NotNull()); 1472 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1473 1474 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1475 ASSERT_THAT(QuxDecl, NotNull()); 1476 1477 ASSERT_TRUE(QuxDecl->getType()->isStructureType()); 1478 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1479 1480 FieldDecl *BazDecl = nullptr; 1481 for (FieldDecl *Field : QuxFields) { 1482 if (Field->getNameAsString() == "Baz") { 1483 BazDecl = Field; 1484 } else { 1485 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1486 } 1487 } 1488 ASSERT_THAT(BazDecl, NotNull()); 1489 1490 const auto *QuxLoc = 1491 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1492 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1493 ASSERT_THAT(QuxVal, NotNull()); 1494 1495 const auto *BazLoc = 1496 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1497 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1498 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1499 1500 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1501 ASSERT_THAT(QuuxDecl, NotNull()); 1502 EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal); 1503 }); 1504 } 1505 1506 TEST(TransferTest, ClassThisMember) { 1507 std::string Code = R"( 1508 class A { 1509 int Bar; 1510 1511 class B { 1512 public: 1513 int Baz; 1514 }; 1515 1516 B Qux; 1517 1518 void target() { 1519 int Foo = Bar; 1520 int Quux = Qux.Baz; 1521 // [[p]] 1522 } 1523 }; 1524 )"; 1525 runDataflow( 1526 Code, 1527 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1528 ASTContext &ASTCtx) { 1529 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1530 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1531 1532 const auto *ThisLoc = 1533 cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation()); 1534 1535 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1536 ASSERT_THAT(BarDecl, NotNull()); 1537 1538 const auto *BarLoc = 1539 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1540 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1541 1542 const Value *BarVal = Env.getValue(*BarLoc); 1543 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1544 1545 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1546 ASSERT_THAT(FooDecl, NotNull()); 1547 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1548 1549 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1550 ASSERT_THAT(QuxDecl, NotNull()); 1551 1552 ASSERT_TRUE(QuxDecl->getType()->isClassType()); 1553 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1554 1555 FieldDecl *BazDecl = nullptr; 1556 for (FieldDecl *Field : QuxFields) { 1557 if (Field->getNameAsString() == "Baz") { 1558 BazDecl = Field; 1559 } else { 1560 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1561 } 1562 } 1563 ASSERT_THAT(BazDecl, NotNull()); 1564 1565 const auto *QuxLoc = 1566 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1567 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1568 ASSERT_THAT(QuxVal, NotNull()); 1569 1570 const auto *BazLoc = 1571 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1572 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1573 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1574 1575 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1576 ASSERT_THAT(QuuxDecl, NotNull()); 1577 EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal); 1578 }); 1579 } 1580 1581 TEST(TransferTest, UnionThisMember) { 1582 std::string Code = R"( 1583 union A { 1584 int Foo; 1585 int Bar; 1586 1587 void target() { 1588 A a; 1589 // Mention the fields to ensure they're included in the analysis. 1590 (void)a.Foo; 1591 (void)a.Bar; 1592 // [[p]] 1593 } 1594 }; 1595 )"; 1596 runDataflow( 1597 Code, 1598 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1599 ASTContext &ASTCtx) { 1600 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1601 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1602 1603 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1604 Env.getThisPointeeStorageLocation()); 1605 ASSERT_THAT(ThisLoc, NotNull()); 1606 1607 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1608 ASSERT_THAT(FooDecl, NotNull()); 1609 1610 const auto *FooLoc = 1611 cast<ScalarStorageLocation>(&ThisLoc->getChild(*FooDecl)); 1612 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 1613 1614 const Value *FooVal = Env.getValue(*FooLoc); 1615 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 1616 1617 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1618 ASSERT_THAT(BarDecl, NotNull()); 1619 1620 const auto *BarLoc = 1621 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1622 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1623 1624 const Value *BarVal = Env.getValue(*BarLoc); 1625 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1626 }); 1627 } 1628 1629 TEST(TransferTest, StructThisInLambda) { 1630 std::string ThisCaptureCode = R"( 1631 struct A { 1632 void frob() { 1633 [this]() { 1634 int Foo = Bar; 1635 // [[p1]] 1636 }(); 1637 } 1638 1639 int Bar; 1640 }; 1641 )"; 1642 runDataflow( 1643 ThisCaptureCode, 1644 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1645 ASTContext &ASTCtx) { 1646 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1")); 1647 const Environment &Env = getEnvironmentAtAnnotation(Results, "p1"); 1648 1649 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1650 Env.getThisPointeeStorageLocation()); 1651 ASSERT_THAT(ThisLoc, NotNull()); 1652 1653 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1654 ASSERT_THAT(BarDecl, NotNull()); 1655 1656 const auto *BarLoc = 1657 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1658 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1659 1660 const Value *BarVal = Env.getValue(*BarLoc); 1661 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1662 1663 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1664 ASSERT_THAT(FooDecl, NotNull()); 1665 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1666 }, 1667 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1668 1669 std::string RefCaptureDefaultCode = R"( 1670 struct A { 1671 void frob() { 1672 [&]() { 1673 int Foo = Bar; 1674 // [[p2]] 1675 }(); 1676 } 1677 1678 int Bar; 1679 }; 1680 )"; 1681 runDataflow( 1682 RefCaptureDefaultCode, 1683 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1684 ASTContext &ASTCtx) { 1685 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2")); 1686 const Environment &Env = getEnvironmentAtAnnotation(Results, "p2"); 1687 1688 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1689 Env.getThisPointeeStorageLocation()); 1690 ASSERT_THAT(ThisLoc, NotNull()); 1691 1692 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1693 ASSERT_THAT(BarDecl, NotNull()); 1694 1695 const auto *BarLoc = 1696 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1697 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1698 1699 const Value *BarVal = Env.getValue(*BarLoc); 1700 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1701 1702 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1703 ASSERT_THAT(FooDecl, NotNull()); 1704 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal); 1705 }, 1706 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1707 1708 std::string FreeFunctionLambdaCode = R"( 1709 void foo() { 1710 int Bar; 1711 [&]() { 1712 int Foo = Bar; 1713 // [[p3]] 1714 }(); 1715 } 1716 )"; 1717 runDataflow( 1718 FreeFunctionLambdaCode, 1719 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1720 ASTContext &ASTCtx) { 1721 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3")); 1722 const Environment &Env = getEnvironmentAtAnnotation(Results, "p3"); 1723 1724 EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull()); 1725 }, 1726 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1727 } 1728 1729 TEST(TransferTest, ConstructorInitializer) { 1730 std::string Code = R"( 1731 struct target { 1732 int Bar; 1733 1734 target(int Foo) : Bar(Foo) { 1735 int Qux = Bar; 1736 // [[p]] 1737 } 1738 }; 1739 )"; 1740 runDataflow( 1741 Code, 1742 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1743 ASTContext &ASTCtx) { 1744 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1745 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1746 1747 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1748 Env.getThisPointeeStorageLocation()); 1749 ASSERT_THAT(ThisLoc, NotNull()); 1750 1751 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1752 ASSERT_THAT(FooDecl, NotNull()); 1753 1754 const auto *FooVal = 1755 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1756 1757 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1758 ASSERT_THAT(QuxDecl, NotNull()); 1759 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1760 }); 1761 } 1762 1763 TEST(TransferTest, DefaultInitializer) { 1764 std::string Code = R"( 1765 struct target { 1766 int Bar; 1767 int Baz = Bar; 1768 1769 target(int Foo) : Bar(Foo) { 1770 int Qux = Baz; 1771 // [[p]] 1772 } 1773 }; 1774 )"; 1775 runDataflow( 1776 Code, 1777 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1778 ASTContext &ASTCtx) { 1779 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1780 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1781 1782 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1783 Env.getThisPointeeStorageLocation()); 1784 ASSERT_THAT(ThisLoc, NotNull()); 1785 1786 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1787 ASSERT_THAT(FooDecl, NotNull()); 1788 1789 const auto *FooVal = 1790 cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None)); 1791 1792 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1793 ASSERT_THAT(QuxDecl, NotNull()); 1794 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal); 1795 }); 1796 } 1797 1798 TEST(TransferTest, DefaultInitializerReference) { 1799 std::string Code = R"( 1800 struct target { 1801 int &Bar; 1802 int &Baz = Bar; 1803 1804 target(int &Foo) : Bar(Foo) { 1805 int &Qux = Baz; 1806 // [[p]] 1807 } 1808 }; 1809 )"; 1810 runDataflow( 1811 Code, 1812 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1813 ASTContext &ASTCtx) { 1814 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1815 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1816 1817 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1818 Env.getThisPointeeStorageLocation()); 1819 ASSERT_THAT(ThisLoc, NotNull()); 1820 1821 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1822 ASSERT_THAT(FooDecl, NotNull()); 1823 1824 const auto *FooVal = 1825 cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None)); 1826 1827 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1828 ASSERT_THAT(QuxDecl, NotNull()); 1829 1830 const auto *QuxVal = 1831 cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None)); 1832 EXPECT_EQ(&QuxVal->getReferentLoc(), &FooVal->getReferentLoc()); 1833 }); 1834 } 1835 1836 TEST(TransferTest, TemporaryObject) { 1837 std::string Code = R"( 1838 struct A { 1839 int Bar; 1840 }; 1841 1842 void target() { 1843 A Foo = A(); 1844 (void)Foo.Bar; 1845 // [[p]] 1846 } 1847 )"; 1848 runDataflow( 1849 Code, 1850 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1851 ASTContext &ASTCtx) { 1852 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1853 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1854 1855 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1856 ASSERT_THAT(FooDecl, NotNull()); 1857 1858 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1859 ASSERT_THAT(BarDecl, NotNull()); 1860 1861 const auto *FooLoc = cast<AggregateStorageLocation>( 1862 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1863 const auto *BarLoc = 1864 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1865 1866 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1867 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1868 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1869 }); 1870 } 1871 1872 TEST(TransferTest, ElidableConstructor) { 1873 // This test is effectively the same as TransferTest.TemporaryObject, but 1874 // the code is compiled as C++ 14. 1875 std::string Code = R"( 1876 struct A { 1877 int Bar; 1878 }; 1879 1880 void target() { 1881 A Foo = A(); 1882 (void)Foo.Bar; 1883 // [[p]] 1884 } 1885 )"; 1886 runDataflow( 1887 Code, 1888 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1889 ASTContext &ASTCtx) { 1890 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1891 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1892 1893 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1894 ASSERT_THAT(FooDecl, NotNull()); 1895 1896 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1897 ASSERT_THAT(BarDecl, NotNull()); 1898 1899 const auto *FooLoc = cast<AggregateStorageLocation>( 1900 Env.getStorageLocation(*FooDecl, SkipPast::None)); 1901 const auto *BarLoc = 1902 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1903 1904 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1905 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1906 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1907 }, 1908 LangStandard::lang_cxx14); 1909 } 1910 1911 TEST(TransferTest, AssignmentOperator) { 1912 std::string Code = R"( 1913 struct A { 1914 int Baz; 1915 }; 1916 1917 void target() { 1918 A Foo; 1919 A Bar; 1920 (void)Foo.Baz; 1921 // [[p1]] 1922 Foo = Bar; 1923 // [[p2]] 1924 } 1925 )"; 1926 runDataflow( 1927 Code, 1928 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1929 ASTContext &ASTCtx) { 1930 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 1931 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 1932 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 1933 1934 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1935 ASSERT_THAT(FooDecl, NotNull()); 1936 1937 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1938 ASSERT_THAT(BarDecl, NotNull()); 1939 1940 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1941 ASSERT_THAT(BazDecl, NotNull()); 1942 1943 const auto *FooLoc1 = cast<AggregateStorageLocation>( 1944 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 1945 const auto *BarLoc1 = cast<AggregateStorageLocation>( 1946 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 1947 1948 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 1949 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 1950 EXPECT_NE(FooVal1, BarVal1); 1951 1952 const auto *FooBazVal1 = 1953 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 1954 const auto *BarBazVal1 = 1955 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 1956 EXPECT_NE(FooBazVal1, BarBazVal1); 1957 1958 const auto *FooLoc2 = cast<AggregateStorageLocation>( 1959 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 1960 const auto *BarLoc2 = cast<AggregateStorageLocation>( 1961 Env2.getStorageLocation(*BarDecl, SkipPast::None)); 1962 1963 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 1964 const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2)); 1965 EXPECT_EQ(FooVal2, BarVal2); 1966 1967 const auto *FooBazVal2 = 1968 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 1969 const auto *BarBazVal2 = 1970 cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl))); 1971 EXPECT_EQ(FooBazVal2, BarBazVal2); 1972 }); 1973 } 1974 1975 TEST(TransferTest, CopyConstructor) { 1976 std::string Code = R"( 1977 struct A { 1978 int Baz; 1979 }; 1980 1981 void target() { 1982 A Foo; 1983 (void)Foo.Baz; 1984 A Bar = Foo; 1985 // [[p]] 1986 } 1987 )"; 1988 runDataflow( 1989 Code, 1990 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1991 ASTContext &ASTCtx) { 1992 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1993 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1994 1995 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1996 ASSERT_THAT(FooDecl, NotNull()); 1997 1998 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1999 ASSERT_THAT(BarDecl, NotNull()); 2000 2001 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2002 ASSERT_THAT(BazDecl, NotNull()); 2003 2004 const auto *FooLoc = cast<AggregateStorageLocation>( 2005 Env.getStorageLocation(*FooDecl, SkipPast::None)); 2006 const auto *BarLoc = cast<AggregateStorageLocation>( 2007 Env.getStorageLocation(*BarDecl, SkipPast::None)); 2008 2009 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 2010 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 2011 EXPECT_EQ(FooVal, BarVal); 2012 2013 const auto *FooBazVal = 2014 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 2015 const auto *BarBazVal = 2016 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 2017 EXPECT_EQ(FooBazVal, BarBazVal); 2018 }); 2019 } 2020 2021 TEST(TransferTest, CopyConstructorWithParens) { 2022 std::string Code = R"( 2023 struct A { 2024 int Baz; 2025 }; 2026 2027 void target() { 2028 A Foo; 2029 (void)Foo.Baz; 2030 A Bar((A(Foo))); 2031 // [[p]] 2032 } 2033 )"; 2034 runDataflow( 2035 Code, 2036 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2037 ASTContext &ASTCtx) { 2038 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2039 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2040 2041 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2042 ASSERT_THAT(FooDecl, NotNull()); 2043 2044 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2045 ASSERT_THAT(BarDecl, NotNull()); 2046 2047 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2048 ASSERT_THAT(BazDecl, NotNull()); 2049 2050 const auto *FooLoc = cast<AggregateStorageLocation>( 2051 Env.getStorageLocation(*FooDecl, SkipPast::None)); 2052 const auto *BarLoc = cast<AggregateStorageLocation>( 2053 Env.getStorageLocation(*BarDecl, SkipPast::None)); 2054 2055 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 2056 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 2057 EXPECT_EQ(FooVal, BarVal); 2058 2059 const auto *FooBazVal = 2060 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 2061 const auto *BarBazVal = 2062 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 2063 EXPECT_EQ(FooBazVal, BarBazVal); 2064 }); 2065 } 2066 2067 TEST(TransferTest, MoveConstructor) { 2068 std::string Code = R"( 2069 namespace std { 2070 2071 template <typename T> struct remove_reference { using type = T; }; 2072 template <typename T> struct remove_reference<T&> { using type = T; }; 2073 template <typename T> struct remove_reference<T&&> { using type = T; }; 2074 2075 template <typename T> 2076 using remove_reference_t = typename remove_reference<T>::type; 2077 2078 template <typename T> 2079 std::remove_reference_t<T>&& move(T&& x); 2080 2081 } // namespace std 2082 2083 struct A { 2084 int Baz; 2085 }; 2086 2087 void target() { 2088 A Foo; 2089 A Bar; 2090 (void)Foo.Baz; 2091 // [[p1]] 2092 Foo = std::move(Bar); 2093 // [[p2]] 2094 } 2095 )"; 2096 runDataflow( 2097 Code, 2098 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2099 ASTContext &ASTCtx) { 2100 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 2101 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 2102 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 2103 2104 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2105 ASSERT_THAT(FooDecl, NotNull()); 2106 2107 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2108 ASSERT_THAT(BarDecl, NotNull()); 2109 2110 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2111 ASSERT_THAT(BazDecl, NotNull()); 2112 2113 const auto *FooLoc1 = cast<AggregateStorageLocation>( 2114 Env1.getStorageLocation(*FooDecl, SkipPast::None)); 2115 const auto *BarLoc1 = cast<AggregateStorageLocation>( 2116 Env1.getStorageLocation(*BarDecl, SkipPast::None)); 2117 2118 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 2119 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 2120 EXPECT_NE(FooVal1, BarVal1); 2121 2122 const auto *FooBazVal1 = 2123 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 2124 const auto *BarBazVal1 = 2125 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 2126 EXPECT_NE(FooBazVal1, BarBazVal1); 2127 2128 const auto *FooLoc2 = cast<AggregateStorageLocation>( 2129 Env2.getStorageLocation(*FooDecl, SkipPast::None)); 2130 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 2131 EXPECT_EQ(FooVal2, BarVal1); 2132 2133 const auto *FooBazVal2 = 2134 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 2135 EXPECT_EQ(FooBazVal2, BarBazVal1); 2136 }); 2137 } 2138 2139 TEST(TransferTest, BindTemporary) { 2140 std::string Code = R"( 2141 struct A { 2142 virtual ~A() = default; 2143 2144 int Baz; 2145 }; 2146 2147 void target(A Foo) { 2148 int Bar = A(Foo).Baz; 2149 // [[p]] 2150 } 2151 )"; 2152 runDataflow( 2153 Code, 2154 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2155 ASTContext &ASTCtx) { 2156 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2157 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2158 2159 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2160 ASSERT_THAT(FooDecl, NotNull()); 2161 2162 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2163 ASSERT_THAT(BarDecl, NotNull()); 2164 2165 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2166 ASSERT_THAT(BazDecl, NotNull()); 2167 2168 const auto &FooVal = 2169 *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 2170 const auto *BarVal = 2171 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2172 EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl)); 2173 }); 2174 } 2175 2176 TEST(TransferTest, StaticCast) { 2177 std::string Code = R"( 2178 void target(int Foo) { 2179 int Bar = static_cast<int>(Foo); 2180 // [[p]] 2181 } 2182 )"; 2183 runDataflow( 2184 Code, 2185 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2186 ASTContext &ASTCtx) { 2187 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2188 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2189 2190 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2191 ASSERT_THAT(FooDecl, NotNull()); 2192 2193 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2194 ASSERT_THAT(BarDecl, NotNull()); 2195 2196 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2197 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2198 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2199 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2200 EXPECT_EQ(FooVal, BarVal); 2201 }); 2202 } 2203 2204 TEST(TransferTest, IntegralCast) { 2205 std::string Code = R"( 2206 void target(int Foo) { 2207 long Bar = Foo; 2208 // [[p]] 2209 } 2210 )"; 2211 runDataflow( 2212 Code, 2213 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2214 ASTContext &ASTCtx) { 2215 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2216 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2217 2218 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2219 ASSERT_THAT(FooDecl, NotNull()); 2220 2221 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2222 ASSERT_THAT(BarDecl, NotNull()); 2223 2224 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2225 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2226 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2227 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2228 EXPECT_EQ(FooVal, BarVal); 2229 }); 2230 } 2231 2232 TEST(TransferTest, IntegraltoBooleanCast) { 2233 std::string Code = R"( 2234 void target(int Foo) { 2235 bool Bar = Foo; 2236 // [[p]] 2237 } 2238 )"; 2239 runDataflow( 2240 Code, 2241 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2242 ASTContext &ASTCtx) { 2243 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2244 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2245 2246 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2247 ASSERT_THAT(FooDecl, NotNull()); 2248 2249 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2250 ASSERT_THAT(BarDecl, NotNull()); 2251 2252 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2253 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2254 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2255 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2256 }); 2257 } 2258 2259 TEST(TransferTest, IntegralToBooleanCastFromBool) { 2260 std::string Code = R"( 2261 void target(bool Foo) { 2262 int Zab = Foo; 2263 bool Bar = Zab; 2264 // [[p]] 2265 } 2266 )"; 2267 runDataflow( 2268 Code, 2269 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2270 ASTContext &ASTCtx) { 2271 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2272 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2273 2274 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2275 ASSERT_THAT(FooDecl, NotNull()); 2276 2277 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2278 ASSERT_THAT(BarDecl, NotNull()); 2279 2280 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None); 2281 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None); 2282 EXPECT_TRUE(isa<BoolValue>(FooVal)); 2283 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2284 EXPECT_EQ(FooVal, BarVal); 2285 }); 2286 } 2287 2288 TEST(TransferTest, NullToPointerCast) { 2289 std::string Code = R"( 2290 using my_nullptr_t = decltype(nullptr); 2291 struct Baz {}; 2292 void target() { 2293 int *FooX = nullptr; 2294 int *FooY = nullptr; 2295 bool **Bar = nullptr; 2296 Baz *Baz = nullptr; 2297 my_nullptr_t Null = 0; 2298 // [[p]] 2299 } 2300 )"; 2301 runDataflow( 2302 Code, 2303 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2304 ASTContext &ASTCtx) { 2305 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2306 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2307 2308 const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX"); 2309 ASSERT_THAT(FooXDecl, NotNull()); 2310 2311 const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY"); 2312 ASSERT_THAT(FooYDecl, NotNull()); 2313 2314 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2315 ASSERT_THAT(BarDecl, NotNull()); 2316 2317 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2318 ASSERT_THAT(BazDecl, NotNull()); 2319 2320 const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null"); 2321 ASSERT_THAT(NullDecl, NotNull()); 2322 2323 const auto *FooXVal = 2324 cast<PointerValue>(Env.getValue(*FooXDecl, SkipPast::None)); 2325 const auto *FooYVal = 2326 cast<PointerValue>(Env.getValue(*FooYDecl, SkipPast::None)); 2327 const auto *BarVal = 2328 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2329 const auto *BazVal = 2330 cast<PointerValue>(Env.getValue(*BazDecl, SkipPast::None)); 2331 const auto *NullVal = 2332 cast<PointerValue>(Env.getValue(*NullDecl, SkipPast::None)); 2333 2334 EXPECT_EQ(FooXVal, FooYVal); 2335 EXPECT_NE(FooXVal, BarVal); 2336 EXPECT_NE(FooXVal, BazVal); 2337 EXPECT_NE(BarVal, BazVal); 2338 2339 const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc(); 2340 EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc)); 2341 EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull()); 2342 2343 const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc(); 2344 EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc)); 2345 EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull()); 2346 2347 const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc(); 2348 EXPECT_TRUE(isa<AggregateStorageLocation>(BazPointeeLoc)); 2349 EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull()); 2350 2351 const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc(); 2352 EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc)); 2353 EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull()); 2354 }); 2355 } 2356 2357 TEST(TransferTest, NullToMemberPointerCast) { 2358 std::string Code = R"( 2359 struct Foo {}; 2360 void target(Foo *Foo) { 2361 int Foo::*MemberPointer = nullptr; 2362 // [[p]] 2363 } 2364 )"; 2365 runDataflow( 2366 Code, 2367 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2368 ASTContext &ASTCtx) { 2369 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2370 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2371 2372 const ValueDecl *MemberPointerDecl = 2373 findValueDecl(ASTCtx, "MemberPointer"); 2374 ASSERT_THAT(MemberPointerDecl, NotNull()); 2375 2376 const auto *MemberPointerVal = cast<PointerValue>( 2377 Env.getValue(*MemberPointerDecl, SkipPast::None)); 2378 2379 const StorageLocation &MemberLoc = MemberPointerVal->getPointeeLoc(); 2380 EXPECT_THAT(Env.getValue(MemberLoc), IsNull()); 2381 }); 2382 } 2383 2384 TEST(TransferTest, AddrOfValue) { 2385 std::string Code = R"( 2386 void target() { 2387 int Foo; 2388 int *Bar = &Foo; 2389 // [[p]] 2390 } 2391 )"; 2392 runDataflow( 2393 Code, 2394 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2395 ASTContext &ASTCtx) { 2396 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2397 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2398 2399 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2400 ASSERT_THAT(FooDecl, NotNull()); 2401 2402 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2403 ASSERT_THAT(BarDecl, NotNull()); 2404 2405 const auto *FooLoc = cast<ScalarStorageLocation>( 2406 Env.getStorageLocation(*FooDecl, SkipPast::None)); 2407 const auto *BarVal = 2408 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2409 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc); 2410 }); 2411 } 2412 2413 TEST(TransferTest, AddrOfReference) { 2414 std::string Code = R"( 2415 void target(int *Foo) { 2416 int *Bar = &(*Foo); 2417 // [[p]] 2418 } 2419 )"; 2420 runDataflow( 2421 Code, 2422 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2423 ASTContext &ASTCtx) { 2424 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2425 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2426 2427 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2428 ASSERT_THAT(FooDecl, NotNull()); 2429 2430 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2431 ASSERT_THAT(BarDecl, NotNull()); 2432 2433 const auto *FooVal = 2434 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2435 const auto *BarVal = 2436 cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); 2437 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 2438 }); 2439 } 2440 2441 TEST(TransferTest, DerefDependentPtr) { 2442 std::string Code = R"( 2443 template <typename T> 2444 void target(T *Foo) { 2445 T &Bar = *Foo; 2446 /*[[p]]*/ 2447 } 2448 )"; 2449 runDataflow( 2450 Code, 2451 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2452 ASTContext &ASTCtx) { 2453 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2454 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2455 2456 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2457 ASSERT_THAT(FooDecl, NotNull()); 2458 2459 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2460 ASSERT_THAT(BarDecl, NotNull()); 2461 2462 const auto *FooVal = 2463 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2464 const auto *BarVal = 2465 cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None)); 2466 EXPECT_EQ(&BarVal->getReferentLoc(), &FooVal->getPointeeLoc()); 2467 }); 2468 } 2469 2470 TEST(TransferTest, VarDeclInitAssignConditionalOperator) { 2471 std::string Code = R"( 2472 struct A {}; 2473 2474 void target(A Foo, A Bar, bool Cond) { 2475 A Baz = Cond ? Foo : Bar; 2476 /*[[p]]*/ 2477 } 2478 )"; 2479 runDataflow( 2480 Code, 2481 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2482 ASTContext &ASTCtx) { 2483 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2484 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2485 2486 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2487 ASSERT_THAT(FooDecl, NotNull()); 2488 2489 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2490 ASSERT_THAT(BarDecl, NotNull()); 2491 2492 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2493 ASSERT_THAT(BazDecl, NotNull()); 2494 2495 const auto *FooVal = 2496 cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None)); 2497 const auto *BarVal = 2498 cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None)); 2499 2500 const auto *BazVal = 2501 dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None)); 2502 ASSERT_THAT(BazVal, NotNull()); 2503 2504 EXPECT_NE(BazVal, FooVal); 2505 EXPECT_NE(BazVal, BarVal); 2506 }); 2507 } 2508 2509 TEST(TransferTest, VarDeclInDoWhile) { 2510 std::string Code = R"( 2511 void target(int *Foo) { 2512 do { 2513 int Bar = *Foo; 2514 } while (true); 2515 (void)0; 2516 /*[[p]]*/ 2517 } 2518 )"; 2519 runDataflow( 2520 Code, 2521 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2522 ASTContext &ASTCtx) { 2523 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2524 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2525 2526 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2527 ASSERT_THAT(FooDecl, NotNull()); 2528 2529 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2530 ASSERT_THAT(BarDecl, NotNull()); 2531 2532 const auto *FooVal = 2533 cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None)); 2534 const auto *FooPointeeVal = 2535 cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc())); 2536 2537 const auto *BarVal = dyn_cast_or_null<IntegerValue>( 2538 Env.getValue(*BarDecl, SkipPast::None)); 2539 ASSERT_THAT(BarVal, NotNull()); 2540 2541 EXPECT_EQ(BarVal, FooPointeeVal); 2542 }); 2543 } 2544 2545 TEST(TransferTest, AggregateInitialization) { 2546 std::string BracesCode = R"( 2547 struct A { 2548 int Foo; 2549 }; 2550 2551 struct B { 2552 int Bar; 2553 A Baz; 2554 int Qux; 2555 }; 2556 2557 void target(int BarArg, int FooArg, int QuxArg) { 2558 B Quux{BarArg, {FooArg}, QuxArg}; 2559 /*[[p]]*/ 2560 } 2561 )"; 2562 std::string BraceEllisionCode = R"( 2563 struct A { 2564 int Foo; 2565 }; 2566 2567 struct B { 2568 int Bar; 2569 A Baz; 2570 int Qux; 2571 }; 2572 2573 void target(int BarArg, int FooArg, int QuxArg) { 2574 B Quux = {BarArg, FooArg, QuxArg}; 2575 /*[[p]]*/ 2576 } 2577 )"; 2578 for (const std::string &Code : {BracesCode, BraceEllisionCode}) { 2579 runDataflow( 2580 Code, 2581 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2582 ASTContext &ASTCtx) { 2583 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2584 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2585 2586 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2587 ASSERT_THAT(FooDecl, NotNull()); 2588 2589 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2590 ASSERT_THAT(BarDecl, NotNull()); 2591 2592 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2593 ASSERT_THAT(BazDecl, NotNull()); 2594 2595 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2596 ASSERT_THAT(QuxDecl, NotNull()); 2597 2598 const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg"); 2599 ASSERT_THAT(FooArgDecl, NotNull()); 2600 2601 const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg"); 2602 ASSERT_THAT(BarArgDecl, NotNull()); 2603 2604 const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg"); 2605 ASSERT_THAT(QuxArgDecl, NotNull()); 2606 2607 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 2608 ASSERT_THAT(QuuxDecl, NotNull()); 2609 2610 const auto *FooArgVal = 2611 cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None)); 2612 const auto *BarArgVal = 2613 cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None)); 2614 const auto *QuxArgVal = 2615 cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None)); 2616 2617 const auto *QuuxVal = 2618 cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None)); 2619 ASSERT_THAT(QuuxVal, NotNull()); 2620 2621 const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl)); 2622 ASSERT_THAT(BazVal, NotNull()); 2623 2624 EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal); 2625 EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal); 2626 EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal); 2627 }); 2628 } 2629 } 2630 2631 TEST(TransferTest, AssignToUnionMember) { 2632 std::string Code = R"( 2633 union A { 2634 int Foo; 2635 }; 2636 2637 void target(int Bar) { 2638 A Baz; 2639 Baz.Foo = Bar; 2640 // [[p]] 2641 } 2642 )"; 2643 runDataflow( 2644 Code, 2645 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2646 ASTContext &ASTCtx) { 2647 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2648 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2649 2650 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2651 ASSERT_THAT(BazDecl, NotNull()); 2652 ASSERT_TRUE(BazDecl->getType()->isUnionType()); 2653 2654 auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields(); 2655 FieldDecl *FooDecl = nullptr; 2656 for (FieldDecl *Field : BazFields) { 2657 if (Field->getNameAsString() == "Foo") { 2658 FooDecl = Field; 2659 } else { 2660 FAIL() << "Unexpected field: " << Field->getNameAsString(); 2661 } 2662 } 2663 ASSERT_THAT(FooDecl, NotNull()); 2664 2665 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>( 2666 Env.getStorageLocation(*BazDecl, SkipPast::None)); 2667 ASSERT_THAT(BazLoc, NotNull()); 2668 ASSERT_THAT(Env.getValue(*BazLoc), NotNull()); 2669 2670 const auto *BazVal = cast<StructValue>(Env.getValue(*BazLoc)); 2671 const auto *FooValFromBazVal = cast<IntegerValue>(BazVal->getChild(*FooDecl)); 2672 const auto *FooValFromBazLoc = cast<IntegerValue>(Env.getValue(BazLoc->getChild(*FooDecl))); 2673 EXPECT_EQ(FooValFromBazLoc, FooValFromBazVal); 2674 2675 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2676 ASSERT_THAT(BarDecl, NotNull()); 2677 const auto *BarLoc = Env.getStorageLocation(*BarDecl, SkipPast::None); 2678 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 2679 2680 EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazVal); 2681 EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazLoc); 2682 }); 2683 } 2684 2685 TEST(TransferTest, AssignFromBoolLiteral) { 2686 std::string Code = R"( 2687 void target() { 2688 bool Foo = true; 2689 bool Bar = false; 2690 // [[p]] 2691 } 2692 )"; 2693 runDataflow( 2694 Code, 2695 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2696 ASTContext &ASTCtx) { 2697 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2698 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2699 2700 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2701 ASSERT_THAT(FooDecl, NotNull()); 2702 2703 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2704 Env.getValue(*FooDecl, SkipPast::None)); 2705 ASSERT_THAT(FooVal, NotNull()); 2706 2707 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2708 ASSERT_THAT(BarDecl, NotNull()); 2709 2710 const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>( 2711 Env.getValue(*BarDecl, SkipPast::None)); 2712 ASSERT_THAT(BarVal, NotNull()); 2713 2714 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true)); 2715 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false)); 2716 }); 2717 } 2718 2719 TEST(TransferTest, AssignFromCompositeBoolExpression) { 2720 { 2721 std::string Code = R"( 2722 void target(bool Foo, bool Bar, bool Qux) { 2723 bool Baz = (Foo) && (Bar || Qux); 2724 // [[p]] 2725 } 2726 )"; 2727 runDataflow( 2728 Code, 2729 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2730 ASTContext &ASTCtx) { 2731 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2732 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2733 2734 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2735 ASSERT_THAT(FooDecl, NotNull()); 2736 2737 const auto *FooVal = dyn_cast_or_null<BoolValue>( 2738 Env.getValue(*FooDecl, SkipPast::None)); 2739 ASSERT_THAT(FooVal, NotNull()); 2740 2741 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2742 ASSERT_THAT(BarDecl, NotNull()); 2743 2744 const auto *BarVal = dyn_cast_or_null<BoolValue>( 2745 Env.getValue(*BarDecl, SkipPast::None)); 2746 ASSERT_THAT(BarVal, NotNull()); 2747 2748 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2749 ASSERT_THAT(QuxDecl, NotNull()); 2750 2751 const auto *QuxVal = dyn_cast_or_null<BoolValue>( 2752 Env.getValue(*QuxDecl, SkipPast::None)); 2753 ASSERT_THAT(QuxVal, NotNull()); 2754 2755 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2756 ASSERT_THAT(BazDecl, NotNull()); 2757 2758 const auto *BazVal = dyn_cast_or_null<ConjunctionValue>( 2759 Env.getValue(*BazDecl, SkipPast::None)); 2760 ASSERT_THAT(BazVal, NotNull()); 2761 EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal); 2762 2763 const auto *BazRightSubValVal = 2764 cast<DisjunctionValue>(&BazVal->getRightSubValue()); 2765 EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal); 2766 EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal); 2767 }); 2768 } 2769 2770 { 2771 std::string Code = R"( 2772 void target(bool Foo, bool Bar, bool Qux) { 2773 bool Baz = (Foo && Qux) || (Bar); 2774 // [[p]] 2775 } 2776 )"; 2777 runDataflow( 2778 Code, 2779 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2780 ASTContext &ASTCtx) { 2781 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2782 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2783 2784 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2785 ASSERT_THAT(FooDecl, NotNull()); 2786 2787 const auto *FooVal = dyn_cast_or_null<BoolValue>( 2788 Env.getValue(*FooDecl, SkipPast::None)); 2789 ASSERT_THAT(FooVal, NotNull()); 2790 2791 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2792 ASSERT_THAT(BarDecl, NotNull()); 2793 2794 const auto *BarVal = dyn_cast_or_null<BoolValue>( 2795 Env.getValue(*BarDecl, SkipPast::None)); 2796 ASSERT_THAT(BarVal, NotNull()); 2797 2798 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2799 ASSERT_THAT(QuxDecl, NotNull()); 2800 2801 const auto *QuxVal = dyn_cast_or_null<BoolValue>( 2802 Env.getValue(*QuxDecl, SkipPast::None)); 2803 ASSERT_THAT(QuxVal, NotNull()); 2804 2805 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2806 ASSERT_THAT(BazDecl, NotNull()); 2807 2808 const auto *BazVal = dyn_cast_or_null<DisjunctionValue>( 2809 Env.getValue(*BazDecl, SkipPast::None)); 2810 ASSERT_THAT(BazVal, NotNull()); 2811 2812 const auto *BazLeftSubValVal = 2813 cast<ConjunctionValue>(&BazVal->getLeftSubValue()); 2814 EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal); 2815 EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal); 2816 2817 EXPECT_EQ(&BazVal->getRightSubValue(), BarVal); 2818 }); 2819 } 2820 2821 { 2822 std::string Code = R"( 2823 void target(bool A, bool B, bool C, bool D) { 2824 bool Foo = ((A && B) && C) && D; 2825 // [[p]] 2826 } 2827 )"; 2828 runDataflow( 2829 Code, 2830 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2831 ASTContext &ASTCtx) { 2832 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2833 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2834 2835 const ValueDecl *ADecl = findValueDecl(ASTCtx, "A"); 2836 ASSERT_THAT(ADecl, NotNull()); 2837 2838 const auto *AVal = 2839 dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl, SkipPast::None)); 2840 ASSERT_THAT(AVal, NotNull()); 2841 2842 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 2843 ASSERT_THAT(BDecl, NotNull()); 2844 2845 const auto *BVal = 2846 dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl, SkipPast::None)); 2847 ASSERT_THAT(BVal, NotNull()); 2848 2849 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 2850 ASSERT_THAT(CDecl, NotNull()); 2851 2852 const auto *CVal = 2853 dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 2854 ASSERT_THAT(CVal, NotNull()); 2855 2856 const ValueDecl *DDecl = findValueDecl(ASTCtx, "D"); 2857 ASSERT_THAT(DDecl, NotNull()); 2858 2859 const auto *DVal = 2860 dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl, SkipPast::None)); 2861 ASSERT_THAT(DVal, NotNull()); 2862 2863 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2864 ASSERT_THAT(FooDecl, NotNull()); 2865 2866 const auto *FooVal = dyn_cast_or_null<ConjunctionValue>( 2867 Env.getValue(*FooDecl, SkipPast::None)); 2868 ASSERT_THAT(FooVal, NotNull()); 2869 2870 const auto &FooLeftSubVal = 2871 cast<ConjunctionValue>(FooVal->getLeftSubValue()); 2872 const auto &FooLeftLeftSubVal = 2873 cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue()); 2874 EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal); 2875 EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal); 2876 EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal); 2877 EXPECT_EQ(&FooVal->getRightSubValue(), DVal); 2878 }); 2879 } 2880 } 2881 2882 TEST(TransferTest, AssignFromBoolNegation) { 2883 std::string Code = R"( 2884 void target() { 2885 bool Foo = true; 2886 bool Bar = !(Foo); 2887 // [[p]] 2888 } 2889 )"; 2890 runDataflow( 2891 Code, 2892 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2893 ASTContext &ASTCtx) { 2894 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2895 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2896 2897 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2898 ASSERT_THAT(FooDecl, NotNull()); 2899 2900 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>( 2901 Env.getValue(*FooDecl, SkipPast::None)); 2902 ASSERT_THAT(FooVal, NotNull()); 2903 2904 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2905 ASSERT_THAT(BarDecl, NotNull()); 2906 2907 const auto *BarVal = dyn_cast_or_null<NegationValue>( 2908 Env.getValue(*BarDecl, SkipPast::None)); 2909 ASSERT_THAT(BarVal, NotNull()); 2910 2911 EXPECT_EQ(&BarVal->getSubVal(), FooVal); 2912 }); 2913 } 2914 2915 TEST(TransferTest, BuiltinExpect) { 2916 std::string Code = R"( 2917 void target(long Foo) { 2918 long Bar = __builtin_expect(Foo, true); 2919 /*[[p]]*/ 2920 } 2921 )"; 2922 runDataflow( 2923 Code, 2924 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2925 ASTContext &ASTCtx) { 2926 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2927 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2928 2929 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2930 ASSERT_THAT(FooDecl, NotNull()); 2931 2932 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2933 ASSERT_THAT(BarDecl, NotNull()); 2934 2935 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2936 Env.getValue(*BarDecl, SkipPast::None)); 2937 }); 2938 } 2939 2940 // `__builtin_expect` takes and returns a `long` argument, so other types 2941 // involve casts. This verifies that we identify the input and output in that 2942 // case. 2943 TEST(TransferTest, BuiltinExpectBoolArg) { 2944 std::string Code = R"( 2945 void target(bool Foo) { 2946 bool Bar = __builtin_expect(Foo, true); 2947 /*[[p]]*/ 2948 } 2949 )"; 2950 runDataflow( 2951 Code, 2952 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2953 ASTContext &ASTCtx) { 2954 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2955 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2956 2957 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2958 ASSERT_THAT(FooDecl, NotNull()); 2959 2960 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2961 ASSERT_THAT(BarDecl, NotNull()); 2962 2963 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2964 Env.getValue(*BarDecl, SkipPast::None)); 2965 }); 2966 } 2967 2968 TEST(TransferTest, BuiltinUnreachable) { 2969 std::string Code = R"( 2970 void target(bool Foo) { 2971 bool Bar = false; 2972 if (Foo) 2973 Bar = Foo; 2974 else 2975 __builtin_unreachable(); 2976 (void)0; 2977 /*[[p]]*/ 2978 } 2979 )"; 2980 runDataflow( 2981 Code, 2982 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2983 ASTContext &ASTCtx) { 2984 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2985 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2986 2987 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2988 ASSERT_THAT(FooDecl, NotNull()); 2989 2990 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2991 ASSERT_THAT(BarDecl, NotNull()); 2992 2993 // `__builtin_unreachable` promises that the code is 2994 // unreachable, so the compiler treats the "then" branch as the 2995 // only possible predecessor of this statement. 2996 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 2997 Env.getValue(*BarDecl, SkipPast::None)); 2998 }); 2999 } 3000 3001 TEST(TransferTest, BuiltinTrap) { 3002 std::string Code = R"( 3003 void target(bool Foo) { 3004 bool Bar = false; 3005 if (Foo) 3006 Bar = Foo; 3007 else 3008 __builtin_trap(); 3009 (void)0; 3010 /*[[p]]*/ 3011 } 3012 )"; 3013 runDataflow( 3014 Code, 3015 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3016 ASTContext &ASTCtx) { 3017 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3018 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3019 3020 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3021 ASSERT_THAT(FooDecl, NotNull()); 3022 3023 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3024 ASSERT_THAT(BarDecl, NotNull()); 3025 3026 // `__builtin_trap` ensures program termination, so only the 3027 // "then" branch is a predecessor of this statement. 3028 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), 3029 Env.getValue(*BarDecl, SkipPast::None)); 3030 }); 3031 } 3032 3033 TEST(TransferTest, BuiltinDebugTrap) { 3034 std::string Code = R"( 3035 void target(bool Foo) { 3036 bool Bar = false; 3037 if (Foo) 3038 Bar = Foo; 3039 else 3040 __builtin_debugtrap(); 3041 (void)0; 3042 /*[[p]]*/ 3043 } 3044 )"; 3045 runDataflow( 3046 Code, 3047 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3048 ASTContext &ASTCtx) { 3049 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3050 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3051 3052 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3053 ASSERT_THAT(FooDecl, NotNull()); 3054 3055 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3056 ASSERT_THAT(BarDecl, NotNull()); 3057 3058 // `__builtin_debugtrap` doesn't ensure program termination. 3059 EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None), 3060 Env.getValue(*BarDecl, SkipPast::None)); 3061 }); 3062 } 3063 3064 TEST(TransferTest, StaticIntSingleVarDecl) { 3065 std::string Code = R"( 3066 void target() { 3067 static int Foo; 3068 // [[p]] 3069 } 3070 )"; 3071 runDataflow( 3072 Code, 3073 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3074 ASTContext &ASTCtx) { 3075 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3076 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3077 3078 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3079 ASSERT_THAT(FooDecl, NotNull()); 3080 3081 const StorageLocation *FooLoc = 3082 Env.getStorageLocation(*FooDecl, SkipPast::None); 3083 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3084 3085 const Value *FooVal = Env.getValue(*FooLoc); 3086 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3087 }); 3088 } 3089 3090 TEST(TransferTest, StaticIntGroupVarDecl) { 3091 std::string Code = R"( 3092 void target() { 3093 static int Foo, Bar; 3094 (void)0; 3095 // [[p]] 3096 } 3097 )"; 3098 runDataflow( 3099 Code, 3100 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3101 ASTContext &ASTCtx) { 3102 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3103 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3104 3105 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3106 ASSERT_THAT(FooDecl, NotNull()); 3107 3108 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3109 ASSERT_THAT(BarDecl, NotNull()); 3110 3111 const StorageLocation *FooLoc = 3112 Env.getStorageLocation(*FooDecl, SkipPast::None); 3113 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3114 3115 const StorageLocation *BarLoc = 3116 Env.getStorageLocation(*BarDecl, SkipPast::None); 3117 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 3118 3119 const Value *FooVal = Env.getValue(*FooLoc); 3120 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3121 3122 const Value *BarVal = Env.getValue(*BarLoc); 3123 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 3124 3125 EXPECT_NE(FooVal, BarVal); 3126 }); 3127 } 3128 3129 TEST(TransferTest, GlobalIntVarDecl) { 3130 std::string Code = R"( 3131 static int Foo; 3132 3133 void target() { 3134 int Bar = Foo; 3135 int Baz = Foo; 3136 // [[p]] 3137 } 3138 )"; 3139 runDataflow( 3140 Code, 3141 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3142 ASTContext &ASTCtx) { 3143 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3144 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3145 3146 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3147 ASSERT_THAT(BarDecl, NotNull()); 3148 3149 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3150 ASSERT_THAT(BazDecl, NotNull()); 3151 3152 const Value *BarVal = 3153 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3154 const Value *BazVal = 3155 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 3156 EXPECT_EQ(BarVal, BazVal); 3157 }); 3158 } 3159 3160 TEST(TransferTest, StaticMemberIntVarDecl) { 3161 std::string Code = R"( 3162 struct A { 3163 static int Foo; 3164 }; 3165 3166 void target(A a) { 3167 int Bar = a.Foo; 3168 int Baz = a.Foo; 3169 // [[p]] 3170 } 3171 )"; 3172 runDataflow( 3173 Code, 3174 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3175 ASTContext &ASTCtx) { 3176 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3177 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3178 3179 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3180 ASSERT_THAT(BarDecl, NotNull()); 3181 3182 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3183 ASSERT_THAT(BazDecl, NotNull()); 3184 3185 const Value *BarVal = 3186 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3187 const Value *BazVal = 3188 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 3189 EXPECT_EQ(BarVal, BazVal); 3190 }); 3191 } 3192 3193 TEST(TransferTest, StaticMemberRefVarDecl) { 3194 std::string Code = R"( 3195 struct A { 3196 static int &Foo; 3197 }; 3198 3199 void target(A a) { 3200 int Bar = a.Foo; 3201 int Baz = a.Foo; 3202 // [[p]] 3203 } 3204 )"; 3205 runDataflow( 3206 Code, 3207 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3208 ASTContext &ASTCtx) { 3209 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3210 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3211 3212 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3213 ASSERT_THAT(BarDecl, NotNull()); 3214 3215 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3216 ASSERT_THAT(BazDecl, NotNull()); 3217 3218 const Value *BarVal = 3219 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3220 const Value *BazVal = 3221 cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None)); 3222 EXPECT_EQ(BarVal, BazVal); 3223 }); 3224 } 3225 3226 TEST(TransferTest, AssignMemberBeforeCopy) { 3227 std::string Code = R"( 3228 struct A { 3229 int Foo; 3230 }; 3231 3232 void target() { 3233 A A1; 3234 A A2; 3235 int Bar; 3236 A1.Foo = Bar; 3237 A2 = A1; 3238 // [[p]] 3239 } 3240 )"; 3241 runDataflow( 3242 Code, 3243 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3244 ASTContext &ASTCtx) { 3245 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3246 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3247 3248 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3249 ASSERT_THAT(FooDecl, NotNull()); 3250 3251 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3252 ASSERT_THAT(BarDecl, NotNull()); 3253 3254 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); 3255 ASSERT_THAT(A1Decl, NotNull()); 3256 3257 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); 3258 ASSERT_THAT(A2Decl, NotNull()); 3259 3260 const auto *BarVal = 3261 cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None)); 3262 3263 const auto *A2Val = 3264 cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None)); 3265 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal); 3266 }); 3267 } 3268 3269 TEST(TransferTest, BooleanEquality) { 3270 std::string Code = R"( 3271 void target(bool Bar) { 3272 bool Foo = true; 3273 if (Bar == Foo) { 3274 (void)0; 3275 /*[[p-then]]*/ 3276 } else { 3277 (void)0; 3278 /*[[p-else]]*/ 3279 } 3280 } 3281 )"; 3282 runDataflow( 3283 Code, 3284 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3285 ASTContext &ASTCtx) { 3286 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else")); 3287 const Environment &EnvThen = 3288 getEnvironmentAtAnnotation(Results, "p-then"); 3289 const Environment &EnvElse = 3290 getEnvironmentAtAnnotation(Results, "p-else"); 3291 3292 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3293 ASSERT_THAT(BarDecl, NotNull()); 3294 3295 auto &BarValThen = 3296 *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None)); 3297 EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen)); 3298 3299 auto &BarValElse = 3300 *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None)); 3301 EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse)); 3302 }); 3303 } 3304 3305 TEST(TransferTest, BooleanInequality) { 3306 std::string Code = R"( 3307 void target(bool Bar) { 3308 bool Foo = true; 3309 if (Bar != Foo) { 3310 (void)0; 3311 /*[[p-then]]*/ 3312 } else { 3313 (void)0; 3314 /*[[p-else]]*/ 3315 } 3316 } 3317 )"; 3318 runDataflow( 3319 Code, 3320 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3321 ASTContext &ASTCtx) { 3322 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else")); 3323 const Environment &EnvThen = 3324 getEnvironmentAtAnnotation(Results, "p-then"); 3325 const Environment &EnvElse = 3326 getEnvironmentAtAnnotation(Results, "p-else"); 3327 3328 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3329 ASSERT_THAT(BarDecl, NotNull()); 3330 3331 auto &BarValThen = 3332 *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None)); 3333 EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen)); 3334 3335 auto &BarValElse = 3336 *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None)); 3337 EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse)); 3338 }); 3339 } 3340 3341 TEST(TransferTest, CorrelatedBranches) { 3342 std::string Code = R"( 3343 void target(bool B, bool C) { 3344 if (B) { 3345 return; 3346 } 3347 (void)0; 3348 /*[[p0]]*/ 3349 if (C) { 3350 B = true; 3351 /*[[p1]]*/ 3352 } 3353 if (B) { 3354 (void)0; 3355 /*[[p2]]*/ 3356 } 3357 } 3358 )"; 3359 runDataflow( 3360 Code, 3361 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3362 ASTContext &ASTCtx) { 3363 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2")); 3364 3365 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3366 ASSERT_THAT(CDecl, NotNull()); 3367 3368 { 3369 const Environment &Env = getEnvironmentAtAnnotation(Results, "p0"); 3370 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3371 ASSERT_THAT(BDecl, NotNull()); 3372 auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None)); 3373 3374 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal))); 3375 } 3376 3377 { 3378 const Environment &Env = getEnvironmentAtAnnotation(Results, "p1"); 3379 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 3380 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3381 } 3382 3383 { 3384 const Environment &Env = getEnvironmentAtAnnotation(Results, "p2"); 3385 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None)); 3386 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3387 } 3388 }); 3389 } 3390 3391 TEST(TransferTest, LoopWithAssignmentConverges) { 3392 std::string Code = R"( 3393 bool foo(); 3394 3395 void target() { 3396 do { 3397 bool Bar = foo(); 3398 if (Bar) break; 3399 (void)Bar; 3400 /*[[p]]*/ 3401 } while (true); 3402 } 3403 )"; 3404 // The key property that we are verifying is implicit in `runDataflow` -- 3405 // namely, that the analysis succeeds, rather than hitting the maximum number 3406 // of iterations. 3407 runDataflow( 3408 Code, 3409 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3410 ASTContext &ASTCtx) { 3411 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3412 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3413 3414 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3415 ASSERT_THAT(BarDecl, NotNull()); 3416 3417 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 3418 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3419 }); 3420 } 3421 3422 TEST(TransferTest, LoopWithStagedAssignments) { 3423 std::string Code = R"( 3424 bool foo(); 3425 3426 void target() { 3427 bool Bar = false; 3428 bool Err = false; 3429 while (foo()) { 3430 if (Bar) 3431 Err = true; 3432 Bar = true; 3433 /*[[p]]*/ 3434 } 3435 } 3436 )"; 3437 runDataflow( 3438 Code, 3439 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3440 ASTContext &ASTCtx) { 3441 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3442 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3443 3444 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3445 ASSERT_THAT(BarDecl, NotNull()); 3446 const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err"); 3447 ASSERT_THAT(ErrDecl, NotNull()); 3448 3449 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 3450 auto &ErrVal = *cast<BoolValue>(Env.getValue(*ErrDecl, SkipPast::None)); 3451 EXPECT_TRUE(Env.flowConditionImplies(BarVal)); 3452 // An unsound analysis, for example only evaluating the loop once, can 3453 // conclude that `Err` is false. So, we test that this conclusion is not 3454 // reached. 3455 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(ErrVal))); 3456 }); 3457 } 3458 3459 TEST(TransferTest, LoopWithReferenceAssignmentConverges) { 3460 std::string Code = R"( 3461 bool &foo(); 3462 3463 void target() { 3464 do { 3465 bool& Bar = foo(); 3466 if (Bar) break; 3467 (void)Bar; 3468 /*[[p]]*/ 3469 } while (true); 3470 } 3471 )"; 3472 // The key property that we are verifying is that the analysis succeeds, 3473 // rather than hitting the maximum number of iterations. 3474 runDataflow( 3475 Code, 3476 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3477 ASTContext &ASTCtx) { 3478 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3479 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3480 3481 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3482 ASSERT_THAT(BarDecl, NotNull()); 3483 3484 auto &BarVal = 3485 *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference)); 3486 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3487 }); 3488 } 3489 3490 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) { 3491 std::string Code = R"( 3492 struct Lookup { 3493 int x; 3494 }; 3495 3496 void target(Lookup val, bool b) { 3497 const Lookup* l = nullptr; 3498 while (b) { 3499 l = &val; 3500 /*[[p-inner]]*/ 3501 } 3502 (void)0; 3503 /*[[p-outer]]*/ 3504 } 3505 )"; 3506 // The key property that we are verifying is implicit in `runDataflow` -- 3507 // namely, that the analysis succeeds, rather than hitting the maximum number 3508 // of iterations. 3509 runDataflow( 3510 Code, 3511 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3512 ASTContext &ASTCtx) { 3513 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer")); 3514 const Environment &InnerEnv = 3515 getEnvironmentAtAnnotation(Results, "p-inner"); 3516 const Environment &OuterEnv = 3517 getEnvironmentAtAnnotation(Results, "p-outer"); 3518 3519 const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val"); 3520 ASSERT_THAT(ValDecl, NotNull()); 3521 3522 const ValueDecl *LDecl = findValueDecl(ASTCtx, "l"); 3523 ASSERT_THAT(LDecl, NotNull()); 3524 3525 // Inner. 3526 auto *LVal = 3527 dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl, SkipPast::None)); 3528 ASSERT_THAT(LVal, NotNull()); 3529 3530 EXPECT_EQ(&LVal->getPointeeLoc(), 3531 InnerEnv.getStorageLocation(*ValDecl, SkipPast::Reference)); 3532 3533 // Outer. 3534 LVal = 3535 dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl, SkipPast::None)); 3536 ASSERT_THAT(LVal, NotNull()); 3537 3538 // The loop body may not have been executed, so we should not conclude 3539 // that `l` points to `val`. 3540 EXPECT_NE(&LVal->getPointeeLoc(), 3541 OuterEnv.getStorageLocation(*ValDecl, SkipPast::Reference)); 3542 }); 3543 } 3544 3545 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { 3546 std::string Code = R"( 3547 union Union { 3548 int A; 3549 float B; 3550 }; 3551 3552 void foo() { 3553 Union A; 3554 Union B; 3555 A = B; 3556 } 3557 )"; 3558 // This is a crash regression test when calling the transfer function on a 3559 // `CXXThisExpr` that refers to a union. 3560 runDataflow( 3561 Code, 3562 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &, 3563 ASTContext &) {}, 3564 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator="); 3565 } 3566 3567 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) { 3568 std::string Code = R"( 3569 struct A { 3570 int Foo; 3571 int Bar; 3572 }; 3573 3574 void target() { 3575 int Qux; 3576 A Baz; 3577 Baz.Foo = Qux; 3578 auto &FooRef = Baz.Foo; 3579 auto &BarRef = Baz.Bar; 3580 auto &[BoundFooRef, BoundBarRef] = Baz; 3581 // [[p]] 3582 } 3583 )"; 3584 runDataflow( 3585 Code, 3586 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3587 ASTContext &ASTCtx) { 3588 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3589 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3590 3591 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3592 ASSERT_THAT(FooRefDecl, NotNull()); 3593 3594 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3595 ASSERT_THAT(BarRefDecl, NotNull()); 3596 3597 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3598 ASSERT_THAT(QuxDecl, NotNull()); 3599 3600 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3601 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3602 3603 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3604 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3605 3606 const StorageLocation *FooRefLoc = 3607 Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); 3608 ASSERT_THAT(FooRefLoc, NotNull()); 3609 3610 const StorageLocation *BarRefLoc = 3611 Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); 3612 ASSERT_THAT(BarRefLoc, NotNull()); 3613 3614 const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); 3615 ASSERT_THAT(QuxVal, NotNull()); 3616 3617 const StorageLocation *BoundFooRefLoc = 3618 Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference); 3619 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3620 3621 const StorageLocation *BoundBarRefLoc = 3622 Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference); 3623 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3624 3625 EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal); 3626 }); 3627 } 3628 3629 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) { 3630 std::string Code = R"( 3631 struct A { 3632 int &Foo; 3633 int &Bar; 3634 }; 3635 3636 void target(A Baz) { 3637 int Qux; 3638 Baz.Foo = Qux; 3639 auto &FooRef = Baz.Foo; 3640 auto &BarRef = Baz.Bar; 3641 auto &[BoundFooRef, BoundBarRef] = Baz; 3642 // [[p]] 3643 } 3644 )"; 3645 runDataflow( 3646 Code, 3647 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3648 ASTContext &ASTCtx) { 3649 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3650 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3651 3652 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3653 ASSERT_THAT(FooRefDecl, NotNull()); 3654 3655 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3656 ASSERT_THAT(BarRefDecl, NotNull()); 3657 3658 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3659 ASSERT_THAT(QuxDecl, NotNull()); 3660 3661 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3662 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3663 3664 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3665 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3666 3667 const StorageLocation *FooRefLoc = 3668 Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); 3669 ASSERT_THAT(FooRefLoc, NotNull()); 3670 3671 const StorageLocation *BarRefLoc = 3672 Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); 3673 ASSERT_THAT(BarRefLoc, NotNull()); 3674 3675 const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); 3676 ASSERT_THAT(QuxVal, NotNull()); 3677 3678 const StorageLocation *BoundFooRefLoc = 3679 Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference); 3680 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3681 3682 const StorageLocation *BoundBarRefLoc = 3683 Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference); 3684 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3685 3686 EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal); 3687 }); 3688 } 3689 3690 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) { 3691 std::string Code = R"( 3692 struct A { 3693 int Foo; 3694 int Bar; 3695 }; 3696 3697 void target() { 3698 int Qux; 3699 A Baz; 3700 Baz.Foo = Qux; 3701 auto &FooRef = Baz.Foo; 3702 auto &BarRef = Baz.Bar; 3703 auto [BoundFoo, BoundBar] = Baz; 3704 // [[p]] 3705 } 3706 )"; 3707 runDataflow( 3708 Code, 3709 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3710 ASTContext &ASTCtx) { 3711 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3712 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3713 3714 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3715 ASSERT_THAT(FooRefDecl, NotNull()); 3716 3717 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3718 ASSERT_THAT(BarRefDecl, NotNull()); 3719 3720 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 3721 ASSERT_THAT(BoundFooDecl, NotNull()); 3722 3723 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 3724 ASSERT_THAT(BoundBarDecl, NotNull()); 3725 3726 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3727 ASSERT_THAT(QuxDecl, NotNull()); 3728 3729 const StorageLocation *FooRefLoc = 3730 Env.getStorageLocation(*FooRefDecl, SkipPast::Reference); 3731 ASSERT_THAT(FooRefLoc, NotNull()); 3732 3733 const StorageLocation *BarRefLoc = 3734 Env.getStorageLocation(*BarRefDecl, SkipPast::Reference); 3735 ASSERT_THAT(BarRefLoc, NotNull()); 3736 3737 const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None); 3738 ASSERT_THAT(QuxVal, NotNull()); 3739 3740 const StorageLocation *BoundFooLoc = 3741 Env.getStorageLocation(*BoundFooDecl, SkipPast::Reference); 3742 EXPECT_NE(BoundFooLoc, FooRefLoc); 3743 3744 const StorageLocation *BoundBarLoc = 3745 Env.getStorageLocation(*BoundBarDecl, SkipPast::Reference); 3746 EXPECT_NE(BoundBarLoc, BarRefLoc); 3747 3748 EXPECT_EQ(Env.getValue(*BoundFooDecl, SkipPast::Reference), QuxVal); 3749 }); 3750 } 3751 3752 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) { 3753 std::string Code = R"( 3754 namespace std { 3755 using size_t = int; 3756 template <class> struct tuple_size; 3757 template <std::size_t, class> struct tuple_element; 3758 template <class...> class tuple; 3759 3760 namespace { 3761 template <class T, T v> 3762 struct size_helper { static const T value = v; }; 3763 } // namespace 3764 3765 template <class... T> 3766 struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {}; 3767 3768 template <std::size_t I, class... T> 3769 struct tuple_element<I, tuple<T...>> { 3770 using type = __type_pack_element<I, T...>; 3771 }; 3772 3773 template <class...> class tuple {}; 3774 3775 template <std::size_t I, class... T> 3776 typename tuple_element<I, tuple<T...>>::type get(tuple<T...>); 3777 } // namespace std 3778 3779 std::tuple<bool, int> makeTuple(); 3780 3781 void target(bool B) { 3782 auto [BoundFoo, BoundBar] = makeTuple(); 3783 bool Baz; 3784 // Include if-then-else to test interaction of `BindingDecl` with join. 3785 if (B) { 3786 Baz = BoundFoo; 3787 (void)BoundBar; 3788 // [[p1]] 3789 } else { 3790 Baz = BoundFoo; 3791 } 3792 (void)0; 3793 // [[p2]] 3794 } 3795 )"; 3796 runDataflow( 3797 Code, 3798 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3799 ASTContext &ASTCtx) { 3800 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 3801 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 3802 3803 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 3804 ASSERT_THAT(BoundFooDecl, NotNull()); 3805 3806 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 3807 ASSERT_THAT(BoundBarDecl, NotNull()); 3808 3809 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3810 ASSERT_THAT(BazDecl, NotNull()); 3811 3812 const Value *BoundFooValue = 3813 Env1.getValue(*BoundFooDecl, SkipPast::Reference); 3814 ASSERT_THAT(BoundFooValue, NotNull()); 3815 EXPECT_TRUE(isa<BoolValue>(BoundFooValue)); 3816 3817 const Value *BoundBarValue = 3818 Env1.getValue(*BoundBarDecl, SkipPast::Reference); 3819 ASSERT_THAT(BoundBarValue, NotNull()); 3820 EXPECT_TRUE(isa<IntegerValue>(BoundBarValue)); 3821 3822 // Test that a `DeclRefExpr` to a `BindingDecl` works as expected. 3823 EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), BoundFooValue); 3824 3825 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 3826 3827 // Test that `BoundFooDecl` retains the value we expect, after the join. 3828 BoundFooValue = Env2.getValue(*BoundFooDecl, SkipPast::Reference); 3829 EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BoundFooValue); 3830 }); 3831 } 3832 3833 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) { 3834 std::string Code = R"( 3835 namespace std { 3836 using size_t = int; 3837 template <class> struct tuple_size; 3838 template <std::size_t, class> struct tuple_element; 3839 template <class...> class tuple; 3840 3841 namespace { 3842 template <class T, T v> 3843 struct size_helper { static const T value = v; }; 3844 } // namespace 3845 3846 template <class... T> 3847 struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {}; 3848 3849 template <std::size_t I, class... T> 3850 struct tuple_element<I, tuple<T...>> { 3851 using type = __type_pack_element<I, T...>; 3852 }; 3853 3854 template <class...> class tuple {}; 3855 3856 template <std::size_t I, class... T> 3857 typename tuple_element<I, tuple<T...>>::type get(tuple<T...>); 3858 } // namespace std 3859 3860 std::tuple<bool, int> &getTuple(); 3861 3862 void target(bool B) { 3863 auto &[BoundFoo, BoundBar] = getTuple(); 3864 bool Baz; 3865 // Include if-then-else to test interaction of `BindingDecl` with join. 3866 if (B) { 3867 Baz = BoundFoo; 3868 (void)BoundBar; 3869 // [[p1]] 3870 } else { 3871 Baz = BoundFoo; 3872 } 3873 (void)0; 3874 // [[p2]] 3875 } 3876 )"; 3877 runDataflow( 3878 Code, 3879 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3880 ASTContext &ASTCtx) { 3881 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 3882 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 3883 3884 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 3885 ASSERT_THAT(BoundFooDecl, NotNull()); 3886 3887 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 3888 ASSERT_THAT(BoundBarDecl, NotNull()); 3889 3890 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3891 ASSERT_THAT(BazDecl, NotNull()); 3892 3893 const Value *BoundFooValue = 3894 Env1.getValue(*BoundFooDecl, SkipPast::Reference); 3895 ASSERT_THAT(BoundFooValue, NotNull()); 3896 EXPECT_TRUE(isa<BoolValue>(BoundFooValue)); 3897 3898 const Value *BoundBarValue = 3899 Env1.getValue(*BoundBarDecl, SkipPast::Reference); 3900 ASSERT_THAT(BoundBarValue, NotNull()); 3901 EXPECT_TRUE(isa<IntegerValue>(BoundBarValue)); 3902 3903 // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type) 3904 // works as expected. We don't test aliasing properties of the 3905 // reference, because we don't model `std::get` and so have no way to 3906 // equate separate references into the tuple. 3907 EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), BoundFooValue); 3908 3909 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 3910 3911 // Test that `BoundFooDecl` retains the value we expect, after the join. 3912 BoundFooValue = Env2.getValue(*BoundFooDecl, SkipPast::Reference); 3913 EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BoundFooValue); 3914 }); 3915 } 3916 // TODO: ref binding 3917 3918 TEST(TransferTest, BinaryOperatorComma) { 3919 std::string Code = R"( 3920 void target(int Foo, int Bar) { 3921 int &Baz = (Foo, Bar); 3922 // [[p]] 3923 } 3924 )"; 3925 runDataflow( 3926 Code, 3927 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3928 ASTContext &ASTCtx) { 3929 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3930 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3931 3932 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3933 ASSERT_THAT(BarDecl, NotNull()); 3934 3935 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3936 ASSERT_THAT(BazDecl, NotNull()); 3937 3938 const StorageLocation *BarLoc = 3939 Env.getStorageLocation(*BarDecl, SkipPast::Reference); 3940 ASSERT_THAT(BarLoc, NotNull()); 3941 3942 const StorageLocation *BazLoc = 3943 Env.getStorageLocation(*BazDecl, SkipPast::Reference); 3944 EXPECT_EQ(BazLoc, BarLoc); 3945 }); 3946 } 3947 3948 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) { 3949 std::string Code = R"( 3950 void target(bool Foo) { 3951 if (Foo) { 3952 (void)0; 3953 // [[if_then]] 3954 } else { 3955 (void)0; 3956 // [[if_else]] 3957 } 3958 } 3959 )"; 3960 runDataflow( 3961 Code, 3962 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3963 ASTContext &ASTCtx) { 3964 ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else")); 3965 const Environment &ThenEnv = 3966 getEnvironmentAtAnnotation(Results, "if_then"); 3967 const Environment &ElseEnv = 3968 getEnvironmentAtAnnotation(Results, "if_else"); 3969 3970 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3971 ASSERT_THAT(FooDecl, NotNull()); 3972 3973 BoolValue &ThenFooVal = 3974 *cast<BoolValue>(ThenEnv.getValue(*FooDecl, SkipPast::None)); 3975 EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal)); 3976 3977 BoolValue &ElseFooVal = 3978 *cast<BoolValue>(ElseEnv.getValue(*FooDecl, SkipPast::None)); 3979 EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal))); 3980 }); 3981 } 3982 3983 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) { 3984 std::string Code = R"( 3985 void target(bool Foo) { 3986 while (Foo) { 3987 (void)0; 3988 // [[loop_body]] 3989 } 3990 (void)0; 3991 // [[after_loop]] 3992 } 3993 )"; 3994 runDataflow( 3995 Code, 3996 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3997 ASTContext &ASTCtx) { 3998 ASSERT_THAT(Results.keys(), 3999 UnorderedElementsAre("loop_body", "after_loop")); 4000 const Environment &LoopBodyEnv = 4001 getEnvironmentAtAnnotation(Results, "loop_body"); 4002 const Environment &AfterLoopEnv = 4003 getEnvironmentAtAnnotation(Results, "after_loop"); 4004 4005 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4006 ASSERT_THAT(FooDecl, NotNull()); 4007 4008 BoolValue &LoopBodyFooVal = 4009 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 4010 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4011 4012 BoolValue &AfterLoopFooVal = 4013 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None)); 4014 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4015 AfterLoopEnv.makeNot(AfterLoopFooVal))); 4016 }); 4017 } 4018 4019 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) { 4020 std::string Code = R"( 4021 void target(bool Foo) { 4022 bool Bar = true; 4023 do { 4024 (void)0; 4025 // [[loop_body]] 4026 Bar = false; 4027 } while (Foo); 4028 (void)0; 4029 // [[after_loop]] 4030 } 4031 )"; 4032 runDataflow( 4033 Code, 4034 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4035 ASTContext &ASTCtx) { 4036 ASSERT_THAT(Results.keys(), 4037 UnorderedElementsAre("loop_body", "after_loop")); 4038 const Environment &LoopBodyEnv = 4039 getEnvironmentAtAnnotation(Results, "loop_body"); 4040 const Environment &AfterLoopEnv = 4041 getEnvironmentAtAnnotation(Results, "after_loop"); 4042 4043 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4044 ASSERT_THAT(FooDecl, NotNull()); 4045 4046 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4047 ASSERT_THAT(BarDecl, NotNull()); 4048 4049 BoolValue &LoopBodyFooVal = 4050 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 4051 BoolValue &LoopBodyBarVal = 4052 *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl, SkipPast::None)); 4053 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies( 4054 LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal))); 4055 4056 BoolValue &AfterLoopFooVal = 4057 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None)); 4058 BoolValue &AfterLoopBarVal = 4059 *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl, SkipPast::None)); 4060 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4061 AfterLoopEnv.makeNot(AfterLoopFooVal))); 4062 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4063 AfterLoopEnv.makeNot(AfterLoopBarVal))); 4064 }); 4065 } 4066 4067 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) { 4068 std::string Code = R"( 4069 void target(bool Foo) { 4070 for (; Foo;) { 4071 (void)0; 4072 // [[loop_body]] 4073 } 4074 (void)0; 4075 // [[after_loop]] 4076 } 4077 )"; 4078 runDataflow( 4079 Code, 4080 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4081 ASTContext &ASTCtx) { 4082 ASSERT_THAT(Results.keys(), 4083 UnorderedElementsAre("loop_body", "after_loop")); 4084 const Environment &LoopBodyEnv = 4085 getEnvironmentAtAnnotation(Results, "loop_body"); 4086 const Environment &AfterLoopEnv = 4087 getEnvironmentAtAnnotation(Results, "after_loop"); 4088 4089 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4090 ASSERT_THAT(FooDecl, NotNull()); 4091 4092 BoolValue &LoopBodyFooVal = 4093 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 4094 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4095 4096 BoolValue &AfterLoopFooVal = 4097 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None)); 4098 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4099 AfterLoopEnv.makeNot(AfterLoopFooVal))); 4100 }); 4101 } 4102 4103 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) { 4104 std::string Code = R"( 4105 void target(bool Foo) { 4106 for (;;) { 4107 (void)0; 4108 // [[loop_body]] 4109 } 4110 } 4111 )"; 4112 runDataflow( 4113 Code, 4114 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4115 ASTContext &ASTCtx) { 4116 ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body")); 4117 const Environment &LoopBodyEnv = 4118 getEnvironmentAtAnnotation(Results, "loop_body"); 4119 4120 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4121 ASSERT_THAT(FooDecl, NotNull()); 4122 4123 BoolValue &LoopBodyFooVal = 4124 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None)); 4125 EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4126 }); 4127 } 4128 4129 TEST(TransferTest, ContextSensitiveOptionDisabled) { 4130 std::string Code = R"( 4131 bool GiveBool(); 4132 void SetBool(bool &Var) { Var = true; } 4133 4134 void target() { 4135 bool Foo = GiveBool(); 4136 SetBool(Foo); 4137 // [[p]] 4138 } 4139 )"; 4140 runDataflow( 4141 Code, 4142 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4143 ASTContext &ASTCtx) { 4144 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4145 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4146 4147 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4148 ASSERT_THAT(FooDecl, NotNull()); 4149 4150 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4151 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4152 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4153 }, 4154 {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}}); 4155 } 4156 4157 // This test is a regression test, based on a real crash. 4158 TEST(TransferTest, ContextSensitiveReturnReferenceFromNonReferenceLvalue) { 4159 // This code exercises an unusual code path. If we return an lvalue directly, 4160 // the code will catch that it's an l-value based on the `Value`'s kind. If we 4161 // pass through a dummy function, the framework won't populate a value at 4162 // all. In contrast, this code results in a (fresh) value, but it is not 4163 // `ReferenceValue`. This test verifies that we catch this case as well. 4164 std::string Code = R"( 4165 class S {}; 4166 S& target(bool b, S &s) { 4167 return b ? s : s; 4168 // [[p]] 4169 } 4170 )"; 4171 runDataflow( 4172 Code, 4173 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4174 ASTContext &ASTCtx) { 4175 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4176 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4177 4178 auto *Loc = Env.getReturnStorageLocation(); 4179 ASSERT_THAT(Loc, NotNull()); 4180 4181 EXPECT_THAT(Env.getValue(*Loc), IsNull()); 4182 }, 4183 {BuiltinOptions{ContextSensitiveOptions{}}}); 4184 } 4185 4186 TEST(TransferTest, ContextSensitiveDepthZero) { 4187 std::string Code = R"( 4188 bool GiveBool(); 4189 void SetBool(bool &Var) { Var = true; } 4190 4191 void target() { 4192 bool Foo = GiveBool(); 4193 SetBool(Foo); 4194 // [[p]] 4195 } 4196 )"; 4197 runDataflow( 4198 Code, 4199 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4200 ASTContext &ASTCtx) { 4201 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4202 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4203 4204 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4205 ASSERT_THAT(FooDecl, NotNull()); 4206 4207 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4208 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4209 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4210 }, 4211 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}}); 4212 } 4213 4214 TEST(TransferTest, ContextSensitiveSetTrue) { 4215 std::string Code = R"( 4216 bool GiveBool(); 4217 void SetBool(bool &Var) { Var = true; } 4218 4219 void target() { 4220 bool Foo = GiveBool(); 4221 SetBool(Foo); 4222 // [[p]] 4223 } 4224 )"; 4225 runDataflow( 4226 Code, 4227 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4228 ASTContext &ASTCtx) { 4229 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4230 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4231 4232 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4233 ASSERT_THAT(FooDecl, NotNull()); 4234 4235 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4236 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4237 }, 4238 {BuiltinOptions{ContextSensitiveOptions{}}}); 4239 } 4240 4241 TEST(TransferTest, ContextSensitiveSetFalse) { 4242 std::string Code = R"( 4243 bool GiveBool(); 4244 void SetBool(bool &Var) { Var = false; } 4245 4246 void target() { 4247 bool Foo = GiveBool(); 4248 SetBool(Foo); 4249 // [[p]] 4250 } 4251 )"; 4252 runDataflow( 4253 Code, 4254 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4255 ASTContext &ASTCtx) { 4256 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4257 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4258 4259 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4260 ASSERT_THAT(FooDecl, NotNull()); 4261 4262 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4263 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4264 }, 4265 {BuiltinOptions{ContextSensitiveOptions{}}}); 4266 } 4267 4268 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) { 4269 std::string Code = R"( 4270 bool GiveBool(); 4271 void SetBool(bool &Var, bool Val) { Var = Val; } 4272 4273 void target() { 4274 bool Foo = GiveBool(); 4275 bool Bar = GiveBool(); 4276 SetBool(Foo, true); 4277 SetBool(Bar, false); 4278 // [[p]] 4279 } 4280 )"; 4281 runDataflow( 4282 Code, 4283 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4284 ASTContext &ASTCtx) { 4285 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4286 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4287 4288 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4289 ASSERT_THAT(FooDecl, NotNull()); 4290 4291 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4292 ASSERT_THAT(BarDecl, NotNull()); 4293 4294 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4295 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4296 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4297 4298 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 4299 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4300 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4301 }, 4302 {BuiltinOptions{ContextSensitiveOptions{}}}); 4303 } 4304 4305 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) { 4306 std::string Code = R"( 4307 bool GiveBool(); 4308 void SetBool1(bool &Var) { Var = true; } 4309 void SetBool2(bool &Var) { SetBool1(Var); } 4310 4311 void target() { 4312 bool Foo = GiveBool(); 4313 SetBool2(Foo); 4314 // [[p]] 4315 } 4316 )"; 4317 runDataflow( 4318 Code, 4319 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4320 ASTContext &ASTCtx) { 4321 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4322 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4323 4324 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4325 ASSERT_THAT(FooDecl, NotNull()); 4326 4327 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4328 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4329 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4330 }, 4331 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}}); 4332 } 4333 4334 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) { 4335 std::string Code = R"( 4336 bool GiveBool(); 4337 void SetBool1(bool &Var) { Var = true; } 4338 void SetBool2(bool &Var) { SetBool1(Var); } 4339 4340 void target() { 4341 bool Foo = GiveBool(); 4342 SetBool2(Foo); 4343 // [[p]] 4344 } 4345 )"; 4346 runDataflow( 4347 Code, 4348 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4349 ASTContext &ASTCtx) { 4350 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4351 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4352 4353 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4354 ASSERT_THAT(FooDecl, NotNull()); 4355 4356 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4357 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4358 }, 4359 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}}); 4360 } 4361 4362 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) { 4363 std::string Code = R"( 4364 bool GiveBool(); 4365 void SetBool1(bool &Var) { Var = true; } 4366 void SetBool2(bool &Var) { SetBool1(Var); } 4367 void SetBool3(bool &Var) { SetBool2(Var); } 4368 4369 void target() { 4370 bool Foo = GiveBool(); 4371 SetBool3(Foo); 4372 // [[p]] 4373 } 4374 )"; 4375 runDataflow( 4376 Code, 4377 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4378 ASTContext &ASTCtx) { 4379 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4380 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4381 4382 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4383 ASSERT_THAT(FooDecl, NotNull()); 4384 4385 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4386 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4387 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4388 }, 4389 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}}); 4390 } 4391 4392 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) { 4393 std::string Code = R"( 4394 bool GiveBool(); 4395 void SetBool1(bool &Var) { Var = true; } 4396 void SetBool2(bool &Var) { SetBool1(Var); } 4397 void SetBool3(bool &Var) { SetBool2(Var); } 4398 4399 void target() { 4400 bool Foo = GiveBool(); 4401 SetBool3(Foo); 4402 // [[p]] 4403 } 4404 )"; 4405 runDataflow( 4406 Code, 4407 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4408 ASTContext &ASTCtx) { 4409 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4410 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4411 4412 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4413 ASSERT_THAT(FooDecl, NotNull()); 4414 4415 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4416 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4417 }, 4418 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}}); 4419 } 4420 4421 TEST(TransferTest, ContextSensitiveMutualRecursion) { 4422 std::string Code = R"( 4423 bool Pong(bool X, bool Y); 4424 4425 bool Ping(bool X, bool Y) { 4426 if (X) { 4427 return Y; 4428 } else { 4429 return Pong(!X, Y); 4430 } 4431 } 4432 4433 bool Pong(bool X, bool Y) { 4434 if (Y) { 4435 return X; 4436 } else { 4437 return Ping(X, !Y); 4438 } 4439 } 4440 4441 void target() { 4442 bool Foo = Ping(false, false); 4443 // [[p]] 4444 } 4445 )"; 4446 runDataflow( 4447 Code, 4448 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4449 ASTContext &ASTCtx) { 4450 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4451 // The analysis doesn't crash... 4452 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4453 4454 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4455 ASSERT_THAT(FooDecl, NotNull()); 4456 4457 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4458 // ... but it also can't prove anything here. 4459 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4460 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4461 }, 4462 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}}); 4463 } 4464 4465 TEST(TransferTest, ContextSensitiveSetMultipleLines) { 4466 std::string Code = R"( 4467 void SetBools(bool &Var1, bool &Var2) { 4468 Var1 = true; 4469 Var2 = false; 4470 } 4471 4472 void target() { 4473 bool Foo = false; 4474 bool Bar = true; 4475 SetBools(Foo, Bar); 4476 // [[p]] 4477 } 4478 )"; 4479 runDataflow( 4480 Code, 4481 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4482 ASTContext &ASTCtx) { 4483 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4484 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4485 4486 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4487 ASSERT_THAT(FooDecl, NotNull()); 4488 4489 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4490 ASSERT_THAT(BarDecl, NotNull()); 4491 4492 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4493 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4494 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4495 4496 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 4497 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4498 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4499 }, 4500 {BuiltinOptions{ContextSensitiveOptions{}}}); 4501 } 4502 4503 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) { 4504 std::string Code = R"( 4505 void IfCond(bool Cond, bool &Then, bool &Else) { 4506 if (Cond) { 4507 Then = true; 4508 } else { 4509 Else = true; 4510 } 4511 } 4512 4513 void target() { 4514 bool Foo = false; 4515 bool Bar = false; 4516 bool Baz = false; 4517 IfCond(Foo, Bar, Baz); 4518 // [[p]] 4519 } 4520 )"; 4521 runDataflow( 4522 Code, 4523 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4524 ASTContext &ASTCtx) { 4525 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4526 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4527 4528 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4529 ASSERT_THAT(BarDecl, NotNull()); 4530 4531 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4532 ASSERT_THAT(BazDecl, NotNull()); 4533 4534 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None)); 4535 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4536 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4537 4538 auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl, SkipPast::None)); 4539 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 4540 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal))); 4541 }, 4542 {BuiltinOptions{ContextSensitiveOptions{}}}); 4543 } 4544 4545 TEST(TransferTest, ContextSensitiveReturnVoid) { 4546 std::string Code = R"( 4547 void Noop() { return; } 4548 4549 void target() { 4550 Noop(); 4551 // [[p]] 4552 } 4553 )"; 4554 runDataflow( 4555 Code, 4556 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4557 ASTContext &ASTCtx) { 4558 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4559 // This just tests that the analysis doesn't crash. 4560 }, 4561 {BuiltinOptions{ContextSensitiveOptions{}}}); 4562 } 4563 4564 TEST(TransferTest, ContextSensitiveReturnTrue) { 4565 std::string Code = R"( 4566 bool GiveBool() { return true; } 4567 4568 void target() { 4569 bool Foo = GiveBool(); 4570 // [[p]] 4571 } 4572 )"; 4573 runDataflow( 4574 Code, 4575 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4576 ASTContext &ASTCtx) { 4577 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4578 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4579 4580 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4581 ASSERT_THAT(FooDecl, NotNull()); 4582 4583 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4584 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4585 }, 4586 {BuiltinOptions{ContextSensitiveOptions{}}}); 4587 } 4588 4589 TEST(TransferTest, ContextSensitiveReturnFalse) { 4590 std::string Code = R"( 4591 bool GiveBool() { return false; } 4592 4593 void target() { 4594 bool Foo = GiveBool(); 4595 // [[p]] 4596 } 4597 )"; 4598 runDataflow( 4599 Code, 4600 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4601 ASTContext &ASTCtx) { 4602 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4603 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4604 4605 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4606 ASSERT_THAT(FooDecl, NotNull()); 4607 4608 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4609 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4610 }, 4611 {BuiltinOptions{ContextSensitiveOptions{}}}); 4612 } 4613 4614 TEST(TransferTest, ContextSensitiveReturnArg) { 4615 std::string Code = R"( 4616 bool GiveBool(); 4617 bool GiveBack(bool Arg) { return Arg; } 4618 4619 void target() { 4620 bool Foo = GiveBool(); 4621 bool Bar = GiveBack(Foo); 4622 bool Baz = Foo == Bar; 4623 // [[p]] 4624 } 4625 )"; 4626 runDataflow( 4627 Code, 4628 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4629 ASTContext &ASTCtx) { 4630 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4631 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4632 4633 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4634 ASSERT_THAT(BazDecl, NotNull()); 4635 4636 auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl, SkipPast::None)); 4637 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 4638 }, 4639 {BuiltinOptions{ContextSensitiveOptions{}}}); 4640 } 4641 4642 TEST(TransferTest, ContextSensitiveReturnInt) { 4643 std::string Code = R"( 4644 int identity(int x) { return x; } 4645 4646 void target() { 4647 int y = identity(42); 4648 // [[p]] 4649 } 4650 )"; 4651 runDataflow( 4652 Code, 4653 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4654 ASTContext &ASTCtx) { 4655 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4656 // This just tests that the analysis doesn't crash. 4657 }, 4658 {BuiltinOptions{ContextSensitiveOptions{}}}); 4659 } 4660 4661 TEST(TransferTest, ContextSensitiveMethodLiteral) { 4662 std::string Code = R"( 4663 class MyClass { 4664 public: 4665 bool giveBool() { return true; } 4666 }; 4667 4668 void target() { 4669 MyClass MyObj; 4670 bool Foo = MyObj.giveBool(); 4671 // [[p]] 4672 } 4673 )"; 4674 runDataflow( 4675 Code, 4676 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4677 ASTContext &ASTCtx) { 4678 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4679 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4680 4681 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4682 ASSERT_THAT(FooDecl, NotNull()); 4683 4684 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4685 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4686 }, 4687 {BuiltinOptions{ContextSensitiveOptions{}}}); 4688 } 4689 4690 TEST(TransferTest, ContextSensitiveMethodGetter) { 4691 std::string Code = R"( 4692 class MyClass { 4693 public: 4694 bool getField() { return Field; } 4695 4696 bool Field; 4697 }; 4698 4699 void target() { 4700 MyClass MyObj; 4701 MyObj.Field = true; 4702 bool Foo = MyObj.getField(); 4703 // [[p]] 4704 } 4705 )"; 4706 runDataflow( 4707 Code, 4708 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4709 ASTContext &ASTCtx) { 4710 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4711 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4712 4713 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4714 ASSERT_THAT(FooDecl, NotNull()); 4715 4716 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4717 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4718 }, 4719 {BuiltinOptions{ContextSensitiveOptions{}}}); 4720 } 4721 4722 TEST(TransferTest, ContextSensitiveMethodSetter) { 4723 std::string Code = R"( 4724 class MyClass { 4725 public: 4726 void setField(bool Val) { Field = Val; } 4727 4728 bool Field; 4729 }; 4730 4731 void target() { 4732 MyClass MyObj; 4733 MyObj.setField(true); 4734 bool Foo = MyObj.Field; 4735 // [[p]] 4736 } 4737 )"; 4738 runDataflow( 4739 Code, 4740 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4741 ASTContext &ASTCtx) { 4742 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4743 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4744 4745 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4746 ASSERT_THAT(FooDecl, NotNull()); 4747 4748 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4749 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4750 }, 4751 {BuiltinOptions{ContextSensitiveOptions{}}}); 4752 } 4753 4754 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) { 4755 std::string Code = R"( 4756 class MyClass { 4757 public: 4758 bool getField() { return Field; } 4759 void setField(bool Val) { Field = Val; } 4760 4761 private: 4762 bool Field; 4763 }; 4764 4765 void target() { 4766 MyClass MyObj; 4767 MyObj.setField(true); 4768 bool Foo = MyObj.getField(); 4769 // [[p]] 4770 } 4771 )"; 4772 runDataflow( 4773 Code, 4774 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4775 ASTContext &ASTCtx) { 4776 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4777 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4778 4779 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4780 ASSERT_THAT(FooDecl, NotNull()); 4781 4782 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4783 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4784 }, 4785 {BuiltinOptions{ContextSensitiveOptions{}}}); 4786 } 4787 4788 4789 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) { 4790 std::string Code = R"( 4791 class MyClass { 4792 public: 4793 void Inner() { MyField = true; } 4794 void Outer() { Inner(); } 4795 4796 bool MyField; 4797 }; 4798 4799 void target() { 4800 MyClass MyObj; 4801 MyObj.Outer(); 4802 bool Foo = MyObj.MyField; 4803 // [[p]] 4804 } 4805 )"; 4806 runDataflow( 4807 Code, 4808 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4809 ASTContext &ASTCtx) { 4810 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4811 ; 4812 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4813 4814 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4815 ASSERT_THAT(FooDecl, NotNull()); 4816 4817 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4818 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4819 }, 4820 {BuiltinOptions{ContextSensitiveOptions{}}}); 4821 } 4822 4823 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) { 4824 std::string Code = R"( 4825 class MyClass { 4826 public: 4827 bool Inner() { return MyField; } 4828 bool Outer() { return Inner(); } 4829 4830 bool MyField; 4831 }; 4832 4833 void target() { 4834 MyClass MyObj; 4835 MyObj.MyField = true; 4836 bool Foo = MyObj.Outer(); 4837 // [[p]] 4838 } 4839 )"; 4840 runDataflow( 4841 Code, 4842 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4843 ASTContext &ASTCtx) { 4844 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4845 ; 4846 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4847 4848 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4849 ASSERT_THAT(FooDecl, NotNull()); 4850 4851 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4852 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4853 }, 4854 {BuiltinOptions{ContextSensitiveOptions{}}}); 4855 } 4856 4857 TEST(TransferTest, ContextSensitiveConstructorBody) { 4858 std::string Code = R"( 4859 class MyClass { 4860 public: 4861 MyClass() { MyField = true; } 4862 4863 bool MyField; 4864 }; 4865 4866 void target() { 4867 MyClass MyObj; 4868 bool Foo = MyObj.MyField; 4869 // [[p]] 4870 } 4871 )"; 4872 runDataflow( 4873 Code, 4874 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4875 ASTContext &ASTCtx) { 4876 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4877 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4878 4879 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4880 ASSERT_THAT(FooDecl, NotNull()); 4881 4882 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4883 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4884 }, 4885 {BuiltinOptions{ContextSensitiveOptions{}}}); 4886 } 4887 4888 TEST(TransferTest, ContextSensitiveConstructorInitializer) { 4889 std::string Code = R"( 4890 class MyClass { 4891 public: 4892 MyClass() : MyField(true) {} 4893 4894 bool MyField; 4895 }; 4896 4897 void target() { 4898 MyClass MyObj; 4899 bool Foo = MyObj.MyField; 4900 // [[p]] 4901 } 4902 )"; 4903 runDataflow( 4904 Code, 4905 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4906 ASTContext &ASTCtx) { 4907 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4908 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4909 4910 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4911 ASSERT_THAT(FooDecl, NotNull()); 4912 4913 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4914 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4915 }, 4916 {BuiltinOptions{ContextSensitiveOptions{}}}); 4917 } 4918 4919 TEST(TransferTest, ContextSensitiveConstructorDefault) { 4920 std::string Code = R"( 4921 class MyClass { 4922 public: 4923 MyClass() = default; 4924 4925 bool MyField = true; 4926 }; 4927 4928 void target() { 4929 MyClass MyObj; 4930 bool Foo = MyObj.MyField; 4931 // [[p]] 4932 } 4933 )"; 4934 runDataflow( 4935 Code, 4936 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4937 ASTContext &ASTCtx) { 4938 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4939 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4940 4941 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4942 ASSERT_THAT(FooDecl, NotNull()); 4943 4944 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None)); 4945 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4946 }, 4947 {BuiltinOptions{ContextSensitiveOptions{}}}); 4948 } 4949 4950 } // namespace 4951