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