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