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