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